undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
72
test/jdk/java/security/Security/CaseInsensitiveAlgNames.java
Normal file
72
test/jdk/java/security/Security/CaseInsensitiveAlgNames.java
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 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 4093855
|
||||
* @summary Make sure algorithm names provided to getInstance() are
|
||||
* treated case-insensitive
|
||||
*/
|
||||
|
||||
import java.security.*;
|
||||
|
||||
public class CaseInsensitiveAlgNames {
|
||||
|
||||
public static void main(String[] args)
|
||||
throws NoSuchAlgorithmException, NoSuchProviderException {
|
||||
// MessageDigest without provider
|
||||
MessageDigest md = MessageDigest.getInstance("SHA");
|
||||
md = MessageDigest.getInstance("sha");
|
||||
md = MessageDigest.getInstance("Sha-1");
|
||||
md = MessageDigest.getInstance("shA1");
|
||||
|
||||
// MessageDigest with provider
|
||||
md = MessageDigest.getInstance("SHA",
|
||||
System.getProperty("test.provider.name", "SUN"));
|
||||
md = MessageDigest.getInstance("sha",
|
||||
System.getProperty("test.provider.name", "SUN"));
|
||||
md = MessageDigest.getInstance("Sha-1",
|
||||
System.getProperty("test.provider.name", "SUN"));
|
||||
md = MessageDigest.getInstance("shA1",
|
||||
System.getProperty("test.provider.name", "SUN"));
|
||||
|
||||
// KeyPairGenerator without provider
|
||||
KeyPairGenerator kGen = KeyPairGenerator.getInstance("DSA");
|
||||
kGen = KeyPairGenerator.getInstance("dsa");
|
||||
kGen = KeyPairGenerator.getInstance("dSA");
|
||||
kGen = KeyPairGenerator.getInstance("OId.1.2.840.10040.4.1");
|
||||
kGen = KeyPairGenerator.getInstance("1.2.840.10040.4.1");
|
||||
|
||||
// KeyPairGenerator with provider
|
||||
kGen = KeyPairGenerator.getInstance("DSA",
|
||||
System.getProperty("test.provider.name", "SUN"));
|
||||
kGen = KeyPairGenerator.getInstance("dsa",
|
||||
System.getProperty("test.provider.name", "SUN"));
|
||||
kGen = KeyPairGenerator.getInstance("dSA",
|
||||
System.getProperty("test.provider.name", "SUN"));
|
||||
kGen = KeyPairGenerator.getInstance("OId.1.2.840.10040.4.1",
|
||||
System.getProperty("test.provider.name", "SUN"));
|
||||
kGen = KeyPairGenerator.getInstance("1.2.840.10040.4.1",
|
||||
System.getProperty("test.provider.name", "SUN"));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* 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 8159964
|
||||
* @summary Classes from deprivileged modules should get loaded through
|
||||
* Platform Classloader.
|
||||
* @modules java.xml.crypto
|
||||
* jdk.security.auth
|
||||
* jdk.security.jgss
|
||||
* @run main DeprivilegedModuleLoaderTest
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.security.auth.kerberos.KeyTab;
|
||||
import javax.xml.crypto.KeySelectorException;
|
||||
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
||||
import com.sun.security.auth.callback.TextCallbackHandler;
|
||||
import com.sun.security.jgss.AuthorizationDataEntry;
|
||||
|
||||
public class DeprivilegedModuleLoaderTest {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
boolean pass = true;
|
||||
List<Class<?>> classes = getDeprivilegedClasses();
|
||||
for (Class<?> cls : classes) {
|
||||
try {
|
||||
pass &= testPlatformClassLoader(cls);
|
||||
} catch (Exception exc) {
|
||||
exc.printStackTrace(System.out);
|
||||
pass = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pass) {
|
||||
throw new RuntimeException("Atleast one test failed.");
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Class<?>> getDeprivilegedClasses() {
|
||||
|
||||
List<Class<?>> classes = new ArrayList<Class<?>>();
|
||||
// Test from java.xml.crypto/javax/xml/crypto/dsig package
|
||||
classes.add(XMLSignatureFactory.class);
|
||||
// Test from java.xml.crypto/javax/xml/crypto package
|
||||
classes.add(KeySelectorException.class);
|
||||
// Test From java.security.jgss/javax/security/auth/kerberos package
|
||||
classes.add(KeyTab.class);
|
||||
// Test from jdk.security.jgss/com/sun/security/jgss package
|
||||
classes.add(AuthorizationDataEntry.class);
|
||||
// Test from jdk.security.auth/com/sun/security/auth/callback package
|
||||
classes.add(TextCallbackHandler.class);
|
||||
return classes;
|
||||
}
|
||||
|
||||
private static boolean testPlatformClassLoader(Class<?> cls) {
|
||||
|
||||
ClassLoader loader = cls.getClassLoader();
|
||||
if (loader == null) {
|
||||
throw new RuntimeException(String.format(
|
||||
"Loaded through Bootstrap Classloader: '%s'", cls));
|
||||
} else if (!loader.toString().contains("PlatformClassLoader")) {
|
||||
throw new RuntimeException(String.format(
|
||||
"Not loaded through Platform ClassLoader: '%s'", cls));
|
||||
}
|
||||
System.out.println(String.format(
|
||||
"Pass: '%s' get loaded through PlatformClassLoader", cls));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (c) 2004, 2025, 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 5094825
|
||||
* @summary verify no deadlock if crypto provider in other classloader is used to verify signed jars
|
||||
* @library ./Deadlock.jar
|
||||
* @compile provider/HashProvider.java
|
||||
* @run main/othervm/timeout=30 ClassLoaderDeadlock
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
|
||||
import java.security.*;
|
||||
|
||||
public class ClassLoaderDeadlock {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// create a new classloader
|
||||
URL url = new URL("file:provider/");
|
||||
final DelayClassLoader cl = new DelayClassLoader(url);
|
||||
|
||||
// install a provider on the custom class loader as the most prefered provider
|
||||
Class clazz = cl.loadClass("HashProvider");
|
||||
Provider p = (Provider)clazz.newInstance();
|
||||
Security.insertProviderAt(p, 1);
|
||||
|
||||
// add a delay in class loading for reproducability
|
||||
cl.delay = 1000;
|
||||
|
||||
new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
// load a random system class
|
||||
// this locks the DelayClassLoader and after the delay the system class loader
|
||||
Class c1 = cl.loadClass("java.lang.String");
|
||||
System.out.println(c1);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
|
||||
// make sure the other thread got a chance to run and grab the lock
|
||||
Thread.sleep(200);
|
||||
|
||||
// load a random class from a signed JAR file to trigger JAR signature verification
|
||||
// locks system class loader first and then tries to lock DelayClassLoader to load the hashes
|
||||
// DEADLOCK HAPPENS HERE
|
||||
Class c2 = Class.forName("com.abc.Tst1");
|
||||
|
||||
// NOT REACHED
|
||||
System.out.println(c2);
|
||||
|
||||
System.out.println("OK");
|
||||
}
|
||||
|
||||
static class DelayClassLoader extends URLClassLoader {
|
||||
|
||||
volatile int delay;
|
||||
|
||||
DelayClassLoader(URL url) {
|
||||
super(new URL[] {url});
|
||||
}
|
||||
|
||||
protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||
System.out.println("-loadClass(" + name + "," + resolve + ")");
|
||||
try {
|
||||
// delay so that we hold the lock for a longer period
|
||||
// makes it much easier to reproduce
|
||||
Thread.sleep(delay);
|
||||
} catch (InterruptedException e) { e.printStackTrace(); }
|
||||
return super.loadClass(name, resolve);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
BIN
test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.jar
Normal file
BIN
test/jdk/java/security/Security/ClassLoaderDeadlock/Deadlock.jar
Normal file
Binary file not shown.
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2025, 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 4944382
|
||||
* @summary make sure we do not deadlock loading signed JAR with getInstance()
|
||||
* @library ./Deadlock.jar
|
||||
* @run main/othervm/timeout=30 Deadlock
|
||||
*/
|
||||
|
||||
import java.security.*;
|
||||
|
||||
public class Deadlock implements Runnable {
|
||||
|
||||
private volatile Exception exc;
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
|
||||
System.out.println("getInstance() ok: " + random);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception during getInstance() call: " + e);
|
||||
this.exc = e;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Deadlock d = new Deadlock();
|
||||
Thread t = new Thread(d);
|
||||
t.start();
|
||||
String className = (args.length == 0) ? "com.abc.Tst1" : args[0];
|
||||
System.out.println("Loading class: " + className);
|
||||
ClassLoader cl = ClassLoader.getSystemClassLoader();
|
||||
System.out.println("SystemClassLoader: " + cl);
|
||||
Class clazz = cl.loadClass(className);
|
||||
System.out.println("OK: " + clazz);
|
||||
t.join();
|
||||
if (d.exc != null) {
|
||||
throw d.exc;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2004, 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.
|
||||
*/
|
||||
|
||||
// See bug 5094825 / ClassLoadDeadlock.sh
|
||||
|
||||
import java.security.*;
|
||||
|
||||
public final class HashProvider extends Provider {
|
||||
public HashProvider() {
|
||||
super("HashProvider", "1.0", "");
|
||||
// register all algorithms from the following providers into this provider
|
||||
// the security framework will try to load them via the classloader of this provider
|
||||
addAlgorithms("SunRsaSign");
|
||||
addAlgorithms("SunJSSE");
|
||||
addAlgorithms("SUN");
|
||||
}
|
||||
|
||||
private void addAlgorithms(String name) {
|
||||
Provider p = Security.getProvider(name);
|
||||
if (p != null) {
|
||||
System.out.println("Adding algorithms from provider " + name + " (" + p.size() + ")");
|
||||
putAll(p);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
58
test/jdk/java/security/Security/NoInstalledProviders.java
Normal file
58
test/jdk/java/security/Security/NoInstalledProviders.java
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2025, 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 4273454 7054918 7052537
|
||||
* @library /test/lib
|
||||
* @summary Make sure getProviders(filter) doesn't throw NPE
|
||||
* @run main/othervm NoInstalledProviders
|
||||
*/
|
||||
|
||||
import java.security.*;
|
||||
import jdk.test.lib.security.ProvidersSnapshot;
|
||||
|
||||
public class NoInstalledProviders {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ProvidersSnapshot snapshot = ProvidersSnapshot.create();
|
||||
try {
|
||||
main0(args);
|
||||
} finally {
|
||||
snapshot.restore();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main0(String[] args) throws Exception {
|
||||
|
||||
Provider[] provs = Security.getProviders();
|
||||
// make sure there are no providers in the system
|
||||
for(int i = 0; i < provs.length; i++ ) {
|
||||
Security.removeProvider( provs[i].getName());
|
||||
}
|
||||
|
||||
String filter = "Signature.SHA1withDSA";
|
||||
|
||||
provs = Security.getProviders(filter);
|
||||
}
|
||||
}
|
||||
98
test/jdk/java/security/Security/Nulls.java
Normal file
98
test/jdk/java/security/Security/Nulls.java
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 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 4960208
|
||||
* @summary verify behavior passing null to various java.security.Security methods
|
||||
* @author Andreas Sterbenz
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import java.security.*;
|
||||
|
||||
public class Nulls {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
try {
|
||||
Security.addProvider(null);
|
||||
throw new Exception();
|
||||
} catch (NullPointerException e) {
|
||||
System.out.println("addProvider(null): " + e);
|
||||
}
|
||||
if (Security.getAlgorithms(null).isEmpty() == false) {
|
||||
throw new Exception();
|
||||
}
|
||||
try {
|
||||
Security.getProperty(null);
|
||||
throw new Exception();
|
||||
} catch (NullPointerException e) {
|
||||
System.out.println("getProperty(null): " + e);
|
||||
}
|
||||
if (Security.getProvider(null) != null) {
|
||||
throw new Exception();
|
||||
}
|
||||
try {
|
||||
Security.getProviders((Map)null);
|
||||
throw new Exception();
|
||||
} catch (NullPointerException e) {
|
||||
System.out.println("getProviders((Map)null): " + e);
|
||||
}
|
||||
try {
|
||||
Security.getProviders((String)null);
|
||||
throw new Exception();
|
||||
} catch (NullPointerException e) {
|
||||
System.out.println("getProviders((String)null): " + e);
|
||||
}
|
||||
try {
|
||||
Security.insertProviderAt(null, 1);
|
||||
throw new Exception();
|
||||
} catch (NullPointerException e) {
|
||||
System.out.println("insertProviderAt(null): " + e);
|
||||
}
|
||||
Security.removeProvider(null);
|
||||
try {
|
||||
Security.setProperty("foo", null);
|
||||
throw new Exception();
|
||||
} catch (NullPointerException e) {
|
||||
System.out.println("setProperty(\"foo\", null): " + e);
|
||||
}
|
||||
try {
|
||||
Security.setProperty(null, "foo");
|
||||
throw new Exception();
|
||||
} catch (NullPointerException e) {
|
||||
System.out.println("setProperty(null, \"foo\"): " + e);
|
||||
}
|
||||
try {
|
||||
Security.setProperty(null, null);
|
||||
throw new Exception();
|
||||
} catch (NullPointerException e) {
|
||||
System.out.println("setProperty(null, null): " + e);
|
||||
}
|
||||
if (Security.getAlgorithmProperty(null, null) != null) {
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
156
test/jdk/java/security/Security/ProviderFiltering.java
Normal file
156
test/jdk/java/security/Security/ProviderFiltering.java
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* 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
|
||||
* @library /test/lib
|
||||
* @bug 6447816
|
||||
* @summary Check that provider service matching/filtering is done correctly
|
||||
* @run main/othervm ProviderFiltering
|
||||
*/
|
||||
import jdk.test.lib.Utils;
|
||||
import java.util.*;
|
||||
import java.security.*;
|
||||
|
||||
public class ProviderFiltering {
|
||||
|
||||
private static void doit(Object filter, String... expectedPNs) {
|
||||
System.out.println("Filter: " + filter);
|
||||
System.out.println("Expected Provider(s): " +
|
||||
(expectedPNs.length > 0 ? Arrays.toString(expectedPNs) :
|
||||
"<NONE>"));
|
||||
Provider ps[];
|
||||
if (filter instanceof String filterStr) {
|
||||
ps = Security.getProviders(filterStr);
|
||||
} else if (filter instanceof Map filterMap) {
|
||||
ps = Security.getProviders(filterMap);
|
||||
} else {
|
||||
throw new RuntimeException("Error: unknown input type: " + filter);
|
||||
}
|
||||
|
||||
if (ps == null) {
|
||||
if (expectedPNs.length != 0) {
|
||||
throw new RuntimeException("Fail: expected provider(s) " +
|
||||
"not found");
|
||||
}
|
||||
} else {
|
||||
if (ps.length == expectedPNs.length) {
|
||||
// check the provider names
|
||||
for (int i = 0; i < ps.length; i++) {
|
||||
if (!ps[i].getName().equals(expectedPNs[i])) {
|
||||
throw new RuntimeException("Fail: provider name " +
|
||||
"mismatch at index " + i + ", got " +
|
||||
ps[i].getName());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Fail: # of providers mismatch");
|
||||
}
|
||||
}
|
||||
System.out.println("=> Passed");
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args)
|
||||
throws NoSuchAlgorithmException {
|
||||
// test filter parsing
|
||||
String[] invalidFilters = { "", "Cipher.", ".RC2 ", "Cipher.RC2 :",
|
||||
"Cipher.RC2 a: ", "Cipher.RC2 :b",
|
||||
"Cipher.RC2 SupportedKeyClasses:a|b"
|
||||
};
|
||||
for (String i : invalidFilters) {
|
||||
System.out.println("Testing IPE for :" + i);
|
||||
Utils.runAndCheckException(()-> Security.getProviders(i),
|
||||
InvalidParameterException.class);
|
||||
}
|
||||
|
||||
String p = "SUN";
|
||||
|
||||
// test alias
|
||||
doit("Signature.NONEwithDSA", p);
|
||||
|
||||
String sigService = "Signature.SHA256withDSA";
|
||||
// javadoc allows extra spaces in between
|
||||
String key = sigService + " SupportedKeyClasses";
|
||||
String valComp1 = "java.security.interfaces.DSAPublicKey";
|
||||
String valComp2 = "java.security.interfaces.DSAPrivateKey";
|
||||
String valComp2CN = valComp2.substring(valComp2.lastIndexOf('.') + 1);
|
||||
|
||||
// test using String filter
|
||||
doit(key + ":" + valComp1, p);
|
||||
doit(key + ":" + valComp2, p);
|
||||
// current impl does matching on individual attribute value for
|
||||
// attributes with composite values; no partial match
|
||||
doit(key + ":" + valComp2CN);
|
||||
|
||||
// repeat above tests using filter Map
|
||||
Map<String,String> filters = new HashMap<>();
|
||||
// match existing behavior; return null if empty filter map
|
||||
doit(filters);
|
||||
filters.put(key, valComp1);
|
||||
doit(filters, p);
|
||||
filters.put(key, valComp2);
|
||||
doit(filters, p);
|
||||
filters.put(key, valComp2CN);
|
||||
doit(filters);
|
||||
|
||||
// try non-attribute filters
|
||||
filters.clear();
|
||||
filters.put(sigService, "");
|
||||
doit(filters, p);
|
||||
filters.put("Cipher.RC2", "");
|
||||
doit(filters);
|
||||
|
||||
// test against a custom provider and attribute
|
||||
filters.clear();
|
||||
String customKey = "customAttr";
|
||||
String customValue = "customValue";
|
||||
String pName = "TestProv";
|
||||
Provider testProv = new TestProvider(pName, sigService, customKey,
|
||||
customValue);
|
||||
Security.insertProviderAt(testProv, 1);
|
||||
// should find both TestProv and SUN and in this order
|
||||
doit(sigService, pName, "SUN");
|
||||
filters.put(sigService, "");
|
||||
doit(filters, pName, "SUN");
|
||||
|
||||
String specAttr = sigService + " " + customKey + ":" + customValue;
|
||||
// should find only TestProv
|
||||
doit(specAttr, pName);
|
||||
filters.put(sigService + " " + customKey, customValue);
|
||||
doit(filters, pName);
|
||||
|
||||
// should find no provider now that TestProv is removed
|
||||
Security.removeProvider(pName);
|
||||
doit(specAttr);
|
||||
}
|
||||
|
||||
private static class TestProvider extends Provider {
|
||||
TestProvider(String name, String service, String attrKey,
|
||||
String attrValue) {
|
||||
super(name, "0.0", "Not for use in production systems!");
|
||||
put(service, "a.b.c");
|
||||
put(service + " " + attrKey, attrValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,937 @@
|
|||
/*
|
||||
* Copyright (c) 2022, 2026, 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.
|
||||
*/
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import jdk.test.lib.Utils;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.util.FileUtils;
|
||||
import sun.net.www.ParseUtil;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.security.Security;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Tests security properties passed through java.security,
|
||||
* java.security.properties or included from other properties files.
|
||||
* @bug 4303068 8155246 8292297 8292177 8281658 8319332
|
||||
* @modules java.base/sun.net.www
|
||||
* @library /test/lib
|
||||
* @run main ExtraFileAndIncludes
|
||||
*/
|
||||
|
||||
public class ExtraFileAndIncludes {
|
||||
static final String SEPARATOR_THIN = "----------------------------";
|
||||
|
||||
private static void printTestHeader(String testName) {
|
||||
System.out.println();
|
||||
System.out.println(SEPARATOR_THIN);
|
||||
System.out.println(testName);
|
||||
System.out.println(SEPARATOR_THIN);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length == 1 && Executor.RUNNER_ARG.equals(args[0])) {
|
||||
// Executed by a test-launched JVM.
|
||||
// Force the initialization of java.security.Security.
|
||||
Security.getProviders();
|
||||
Security.setProperty("postInitTest", "shouldNotRecord");
|
||||
System.out.println(FilesManager.LAST_FILE_PROP_NAME + ": " +
|
||||
Security.getProperty(FilesManager.LAST_FILE_PROP_NAME));
|
||||
assertTestSecuritySetPropertyShouldNotInclude();
|
||||
} else {
|
||||
// Executed by the test JVM.
|
||||
try (FilesManager filesMgr = new FilesManager()) {
|
||||
for (Method m :
|
||||
ExtraFileAndIncludes.class.getDeclaredMethods()) {
|
||||
if (m.getName().startsWith("test")) {
|
||||
printTestHeader(m.getName());
|
||||
Executor.run(m, filesMgr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Success cases
|
||||
*/
|
||||
|
||||
static void testShowSettings(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
// Sanity test passing the -XshowSettings:security option.
|
||||
ex.addJvmArg("-XshowSettings:security");
|
||||
ex.setMasterFile(filesMgr.newMasterFile());
|
||||
ex.assertSuccess();
|
||||
ex.getOutputAnalyzer()
|
||||
.shouldContain("Security properties:")
|
||||
.shouldContain("Security provider static configuration:")
|
||||
.shouldContain("Security TLS configuration");
|
||||
}
|
||||
|
||||
static void testIncludeBasic(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
PropsFile masterFile = filesMgr.newMasterFile();
|
||||
ExtraPropsFile extraFile = filesMgr.newExtraFile(ExtraMode.FILE_URI);
|
||||
PropsFile file0 = filesMgr.newFile("file0.properties");
|
||||
PropsFile file1 = filesMgr.newFile("dir1/file1.properties");
|
||||
PropsFile file2 = filesMgr.newFile("dir1/dir2/file2.properties");
|
||||
|
||||
masterFile.addAbsoluteInclude(file0);
|
||||
extraFile.addRelativeInclude(file2);
|
||||
file2.addAbsoluteInclude(file1);
|
||||
|
||||
ex.setMasterFile(masterFile);
|
||||
ex.setExtraFile(extraFile, false);
|
||||
ex.assertSuccess();
|
||||
}
|
||||
|
||||
static void testRepeatedInclude(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
PropsFile masterFile = filesMgr.newMasterFile();
|
||||
PropsFile file0 = filesMgr.newFile("file0.properties");
|
||||
PropsFile file1 = filesMgr.newFile("dir1/file1.properties");
|
||||
|
||||
masterFile.addAbsoluteInclude(file0);
|
||||
masterFile.addAbsoluteInclude(file1);
|
||||
masterFile.addAbsoluteInclude(file0);
|
||||
file1.addRelativeInclude(file0);
|
||||
|
||||
ex.setMasterFile(masterFile);
|
||||
ex.assertSuccess();
|
||||
}
|
||||
|
||||
static void testIncludeWithOverrideAll(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
PropsFile masterFile = filesMgr.newMasterFile();
|
||||
ExtraPropsFile extraFile = filesMgr.newExtraFile(ExtraMode.HTTP_SERVED);
|
||||
PropsFile file0 = filesMgr.newFile("file0.properties");
|
||||
PropsFile file1 = filesMgr.newFile("dir1/file1.properties");
|
||||
|
||||
masterFile.addRelativeInclude(file0);
|
||||
extraFile.addAbsoluteInclude(file1);
|
||||
|
||||
ex.setMasterFile(masterFile);
|
||||
ex.setExtraFile(extraFile, true);
|
||||
ex.assertSuccess();
|
||||
}
|
||||
|
||||
static void extraPropertiesByHelper(Executor ex, FilesManager filesMgr,
|
||||
ExtraMode mode) throws Exception {
|
||||
ExtraPropsFile extraFile = filesMgr.newExtraFile(mode);
|
||||
PropsFile file0 = filesMgr.newFile("file0.properties");
|
||||
|
||||
extraFile.addRelativeInclude(file0);
|
||||
|
||||
ex.setMasterFile(filesMgr.newMasterFile());
|
||||
ex.setExtraFile(extraFile, true);
|
||||
ex.assertSuccess();
|
||||
}
|
||||
|
||||
static void testExtraPropertiesByPathAbsolute(Executor ex,
|
||||
FilesManager filesMgr) throws Exception {
|
||||
extraPropertiesByHelper(ex, filesMgr, ExtraMode.PATH_ABS);
|
||||
}
|
||||
|
||||
static void testExtraPropertiesByPathRelative(Executor ex,
|
||||
FilesManager filesMgr) throws Exception {
|
||||
extraPropertiesByHelper(ex, filesMgr, ExtraMode.PATH_REL);
|
||||
}
|
||||
|
||||
static void specialCharsIncludes(Executor ex, FilesManager filesMgr,
|
||||
char specialChar, ExtraMode extraMode, boolean useRelativeIncludes)
|
||||
throws Exception {
|
||||
String suffix = specialChar + ".properties";
|
||||
ExtraPropsFile extraFile;
|
||||
PropsFile file0, file1;
|
||||
try {
|
||||
extraFile = filesMgr.newExtraFile("extra" + suffix, extraMode);
|
||||
file0 = filesMgr.newFile("file0" + suffix);
|
||||
file1 = filesMgr.newFile("file1" + suffix);
|
||||
} catch (InvalidPathException ipe) {
|
||||
// The platform encoding may not allow to create files with some
|
||||
// special characters. Skip the test in these cases.
|
||||
return;
|
||||
}
|
||||
|
||||
if (useRelativeIncludes) {
|
||||
extraFile.addRelativeInclude(file0);
|
||||
} else {
|
||||
extraFile.addAbsoluteInclude(file0);
|
||||
}
|
||||
extraFile.addAbsoluteInclude(file1);
|
||||
|
||||
ex.setMasterFile(filesMgr.newMasterFile());
|
||||
ex.setExtraFile(extraFile, false);
|
||||
ex.assertSuccess();
|
||||
}
|
||||
|
||||
static void testUnicodeIncludes1(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
specialCharsIncludes(ex, filesMgr, '\u2022', ExtraMode.PATH_ABS, true);
|
||||
}
|
||||
|
||||
static void testUnicodeIncludes2(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
specialCharsIncludes(ex, filesMgr, '\u2022', ExtraMode.FILE_URI, true);
|
||||
}
|
||||
|
||||
static void testUnicodeIncludes3(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
// Backward compatibility check. Malformed URLs such as
|
||||
// file:/tmp/extra•.properties are supported for the extra file.
|
||||
// However, relative includes are not allowed in these cases.
|
||||
specialCharsIncludes(ex, filesMgr, '\u2022',
|
||||
ExtraMode.RAW_FILE_URI1, false);
|
||||
}
|
||||
|
||||
static void testUnicodeIncludes4(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
// Backward compatibility check. Malformed URLs such as
|
||||
// file:///tmp/extra•.properties are supported for the extra file.
|
||||
// However, relative includes are not allowed in these cases.
|
||||
specialCharsIncludes(ex, filesMgr, '\u2022',
|
||||
ExtraMode.RAW_FILE_URI2, false);
|
||||
}
|
||||
|
||||
static void testSpaceIncludes1(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
specialCharsIncludes(ex, filesMgr, ' ', ExtraMode.PATH_ABS, true);
|
||||
}
|
||||
|
||||
static void testSpaceIncludes2(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
specialCharsIncludes(ex, filesMgr, ' ', ExtraMode.FILE_URI, true);
|
||||
}
|
||||
|
||||
static void testSpaceIncludes3(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
// Backward compatibility check. Malformed URLs such as
|
||||
// file:/tmp/extra .properties are supported for the extra file.
|
||||
// However, relative includes are not allowed in these cases.
|
||||
specialCharsIncludes(ex, filesMgr, ' ', ExtraMode.RAW_FILE_URI1, false);
|
||||
}
|
||||
|
||||
static void testSpaceIncludes4(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
// Backward compatibility check. Malformed URLs such as
|
||||
// file:///tmp/extra .properties are supported for the extra file.
|
||||
// However, relative includes are not allowed in these cases.
|
||||
specialCharsIncludes(ex, filesMgr, ' ', ExtraMode.RAW_FILE_URI2, false);
|
||||
}
|
||||
|
||||
static void notOverrideOnFailureHelper(Executor ex, FilesManager filesMgr,
|
||||
String nonExistentExtraFile) throws Exception {
|
||||
// An overriding extra properties file that does not exist
|
||||
// should not erase properties from the master file.
|
||||
ex.setIgnoredExtraFile(nonExistentExtraFile, true);
|
||||
ex.setMasterFile(filesMgr.newMasterFile());
|
||||
ex.assertSuccess();
|
||||
ex.getOutputAnalyzer().shouldContain("unable to load security " +
|
||||
"properties from " + nonExistentExtraFile);
|
||||
}
|
||||
|
||||
static void testNotOverrideOnEmptyFailure(Executor ex,
|
||||
FilesManager filesMgr) throws Exception {
|
||||
notOverrideOnFailureHelper(ex, filesMgr, "");
|
||||
ex.getOutputAnalyzer()
|
||||
.shouldContain("Empty extra properties file path");
|
||||
}
|
||||
|
||||
static void testNotOverrideOnURLFailure(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
notOverrideOnFailureHelper(ex, filesMgr,
|
||||
"file:///nonExistentFile.properties");
|
||||
}
|
||||
|
||||
static void testNotOverrideOnPathFailure(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
notOverrideOnFailureHelper(ex, filesMgr, "nonExistentFile.properties");
|
||||
}
|
||||
|
||||
static void testNotOverrideOnDirFailure(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
notOverrideOnFailureHelper(ex, filesMgr, "file:///");
|
||||
ex.getOutputAnalyzer().shouldContain("Is a directory");
|
||||
}
|
||||
|
||||
static void testNotOverrideOnBadFileURLFailure(Executor ex,
|
||||
FilesManager filesMgr) throws Exception {
|
||||
notOverrideOnFailureHelper(ex, filesMgr, "file:///%00");
|
||||
}
|
||||
|
||||
static void testDisabledExtraPropertiesFile(Executor ex,
|
||||
FilesManager filesMgr) throws Exception {
|
||||
PropsFile masterFile = filesMgr.newMasterFile();
|
||||
PropsFile file0 = filesMgr.newFile("file0.properties");
|
||||
|
||||
masterFile.addRawProperty("security.overridePropertiesFile", "false");
|
||||
|
||||
ex.setMasterFile(masterFile);
|
||||
ex.setIgnoredExtraFile(file0.path.toString(), true);
|
||||
ex.assertSuccess();
|
||||
}
|
||||
|
||||
static final String SECURITY_SET_PROP_FILE_PATH =
|
||||
"testSecuritySetPropertyShouldNotInclude.propsFilePath";
|
||||
|
||||
static void testSecuritySetPropertyShouldNotInclude(Executor ex,
|
||||
FilesManager filesMgr) throws Exception {
|
||||
PropsFile masterFile = filesMgr.newMasterFile();
|
||||
PropsFile file0 = filesMgr.newFile("file0.properties");
|
||||
|
||||
ex.addSystemProp(SECURITY_SET_PROP_FILE_PATH, file0.path.toString());
|
||||
ex.setMasterFile(masterFile);
|
||||
ex.assertSuccess();
|
||||
}
|
||||
|
||||
static void assertTestSecuritySetPropertyShouldNotInclude() {
|
||||
// This check is executed by the launched JVM.
|
||||
String propsFilePath = System.getProperty(SECURITY_SET_PROP_FILE_PATH);
|
||||
if (propsFilePath != null) {
|
||||
String name = Path.of(propsFilePath).getFileName().toString();
|
||||
String setPropInvokeRepr = "Security.setProperty(\"include\", " +
|
||||
"\"" + propsFilePath + "\")";
|
||||
try {
|
||||
Security.setProperty("include", propsFilePath);
|
||||
throw new RuntimeException(setPropInvokeRepr + " was " +
|
||||
"expected to throw IllegalArgumentException.");
|
||||
} catch (IllegalArgumentException expected) {}
|
||||
if (FilesManager.APPLIED_PROP_VALUE.equals(
|
||||
Security.getProperty(name))) {
|
||||
throw new RuntimeException(setPropInvokeRepr + " caused " +
|
||||
"a file inclusion.");
|
||||
}
|
||||
try {
|
||||
Security.getProperty("include");
|
||||
throw new RuntimeException("Security.getProperty(\"include\")" +
|
||||
" was expected to throw IllegalArgumentException.");
|
||||
} catch (IllegalArgumentException expected) {}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Error cases
|
||||
*/
|
||||
|
||||
static void testCannotResolveRelativeFromHTTPServed(Executor ex,
|
||||
FilesManager filesMgr) throws Exception {
|
||||
ExtraPropsFile extraFile = filesMgr.newExtraFile(ExtraMode.HTTP_SERVED);
|
||||
PropsFile file0 = filesMgr.newFile("file0.properties");
|
||||
|
||||
extraFile.addRelativeInclude(file0);
|
||||
|
||||
ex.setMasterFile(filesMgr.newMasterFile());
|
||||
ex.setExtraFile(extraFile, true);
|
||||
ex.assertError("InternalError: Cannot resolve '" + file0.fileName +
|
||||
"' relative path when included from a non-regular " +
|
||||
"properties file (e.g. HTTP served file)");
|
||||
}
|
||||
|
||||
static void testCannotIncludeCycles(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
PropsFile masterFile = filesMgr.newMasterFile();
|
||||
PropsFile file0 = filesMgr.newFile("file0.properties");
|
||||
PropsFile file1 = filesMgr.newFile("dir1/file1.properties");
|
||||
|
||||
// Includes chain: master -> file0 -> file1 -> master.
|
||||
file1.addRelativeInclude(masterFile);
|
||||
file0.addRelativeInclude(file1);
|
||||
masterFile.addRelativeInclude(file0);
|
||||
|
||||
ex.setMasterFile(masterFile);
|
||||
ex.assertError("Cyclic include");
|
||||
ex.getOutputAnalyzer().stderrShouldMatch("\\QInternalError: Cyclic " +
|
||||
"include of '\\E[^']+\\Q" + masterFile.fileName + "'\\E");
|
||||
}
|
||||
|
||||
static void testCannotIncludeURL(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
PropsFile masterFile = filesMgr.newMasterFile();
|
||||
ExtraPropsFile extraFile = filesMgr.newExtraFile(ExtraMode.HTTP_SERVED);
|
||||
|
||||
masterFile.addRawProperty("include", extraFile.url.toString());
|
||||
|
||||
ex.setMasterFile(masterFile);
|
||||
ex.assertError("InternalError: Unable to include 'http://127.0.0.1:");
|
||||
}
|
||||
|
||||
static void testCannotIncludeNonexistentFile(Executor ex,
|
||||
FilesManager filesMgr) throws Exception {
|
||||
PropsFile masterFile = filesMgr.newMasterFile();
|
||||
|
||||
String nonexistentPath = "/nonExistentFile.properties";
|
||||
masterFile.addRawProperty("include", nonexistentPath);
|
||||
|
||||
ex.setMasterFile(masterFile);
|
||||
ex.assertError(
|
||||
"InternalError: Unable to include '" + nonexistentPath + "'");
|
||||
}
|
||||
|
||||
static void testMustHaveMasterFile(Executor ex, FilesManager filesMgr)
|
||||
throws Exception {
|
||||
// Launch a JDK without a master java.security file present.
|
||||
ex.assertError("InternalError: Error loading java.security file");
|
||||
}
|
||||
|
||||
static void testMustHaveMasterFileEvenWithExtraFile(Executor ex,
|
||||
FilesManager filesMgr) throws Exception {
|
||||
// Launch a JDK without a master java.security file present, but with an
|
||||
// extra file passed. Since the "security.overridePropertiesFile=true"
|
||||
// security property is missing, it should fail anyway.
|
||||
ex.setExtraFile(filesMgr.newExtraFile(ExtraMode.FILE_URI), true);
|
||||
ex.assertError("InternalError: Error loading java.security file");
|
||||
}
|
||||
}
|
||||
|
||||
sealed class PropsFile permits ExtraPropsFile {
|
||||
protected static final class Include {
|
||||
final PropsFile propsFile;
|
||||
final String value;
|
||||
|
||||
private Include(PropsFile propsFile, String value) {
|
||||
this.propsFile = propsFile;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
static Include of(PropsFile propsFile) {
|
||||
return new Include(propsFile, propsFile.path.toString());
|
||||
}
|
||||
|
||||
static Include of(PropsFile propsFile, String value) {
|
||||
return new Include(propsFile, value);
|
||||
}
|
||||
|
||||
void assertProcessed(OutputAnalyzer oa) {
|
||||
oa.shouldContain("processing include: '" + value + "'");
|
||||
oa.shouldContain("finished processing " + propsFile.displayPath);
|
||||
}
|
||||
}
|
||||
|
||||
protected final List<Include> includes = new ArrayList<>();
|
||||
protected final PrintWriter writer;
|
||||
protected boolean includedFromExtra = false;
|
||||
protected Path displayPath;
|
||||
final String fileName;
|
||||
final Path path;
|
||||
|
||||
PropsFile(String fileName, Path path) throws IOException {
|
||||
this.fileName = fileName;
|
||||
this.path = path;
|
||||
this.displayPath = path;
|
||||
this.writer = new PrintWriter(Files.newOutputStream(path,
|
||||
StandardOpenOption.CREATE, StandardOpenOption.APPEND), true);
|
||||
}
|
||||
|
||||
private static String escape(String text, boolean escapeSpace) {
|
||||
StringBuilder sb = new StringBuilder(text.length());
|
||||
CharBuffer cb = CharBuffer.wrap(text);
|
||||
while (cb.hasRemaining()) {
|
||||
char c = cb.get();
|
||||
if (c == '\\' || escapeSpace && c == ' ') {
|
||||
sb.append('\\');
|
||||
}
|
||||
if (Character.UnicodeBlock.of(c) ==
|
||||
Character.UnicodeBlock.BASIC_LATIN) {
|
||||
sb.append(c);
|
||||
} else {
|
||||
sb.append("\\u%04x".formatted((int) c));
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void addRawProperty(String key, String value, String sep) {
|
||||
writer.println(escape(key, true) + sep + escape(value, false));
|
||||
}
|
||||
|
||||
protected void addIncludeDefinition(Include include) {
|
||||
if (include.propsFile instanceof ExtraPropsFile) {
|
||||
throw new RuntimeException("ExtraPropsFile should not be included");
|
||||
}
|
||||
includes.add(include);
|
||||
addRawProperty("include", include.value, " ");
|
||||
}
|
||||
|
||||
void addComment(String comment) {
|
||||
writer.println("# " + comment);
|
||||
}
|
||||
|
||||
void addRawProperty(String key, String value) {
|
||||
addRawProperty(key, value, "=");
|
||||
}
|
||||
|
||||
void addAbsoluteInclude(PropsFile propsFile) {
|
||||
addIncludeDefinition(Include.of(propsFile));
|
||||
}
|
||||
|
||||
void addRelativeInclude(PropsFile propsFile) {
|
||||
Path rel = path.getParent().relativize(propsFile.path);
|
||||
addIncludeDefinition(Include.of(propsFile, rel.toString()));
|
||||
propsFile.displayPath = displayPath.getParent().resolve(rel);
|
||||
}
|
||||
|
||||
void assertApplied(OutputAnalyzer oa) {
|
||||
oa.shouldContain(Executor.INITIAL_PROP_LOG_MSG + fileName + "=" +
|
||||
FilesManager.APPLIED_PROP_VALUE);
|
||||
for (Include include : includes) {
|
||||
include.propsFile.assertApplied(oa);
|
||||
include.assertProcessed(oa);
|
||||
}
|
||||
}
|
||||
|
||||
void assertWasOverwritten(OutputAnalyzer oa) {
|
||||
oa.shouldNotContain(Executor.INITIAL_PROP_LOG_MSG + fileName + "=" +
|
||||
FilesManager.APPLIED_PROP_VALUE);
|
||||
for (Include include : includes) {
|
||||
if (!include.propsFile.includedFromExtra) {
|
||||
include.propsFile.assertWasOverwritten(oa);
|
||||
}
|
||||
include.assertProcessed(oa);
|
||||
}
|
||||
}
|
||||
|
||||
void markAsIncludedFromExtra() {
|
||||
includedFromExtra = true;
|
||||
for (Include include : includes) {
|
||||
include.propsFile.markAsIncludedFromExtra();
|
||||
}
|
||||
}
|
||||
|
||||
PropsFile getLastFile() {
|
||||
return includes.isEmpty() ?
|
||||
this : includes.getLast().propsFile.getLastFile();
|
||||
}
|
||||
|
||||
void close() {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
enum ExtraMode {
|
||||
HTTP_SERVED, FILE_URI, RAW_FILE_URI1, RAW_FILE_URI2, PATH_ABS, PATH_REL
|
||||
}
|
||||
|
||||
final class ExtraPropsFile extends PropsFile {
|
||||
private static final Path CWD = Path.of(".").toAbsolutePath();
|
||||
private final Map<String, String> systemProps = new LinkedHashMap<>();
|
||||
private final ExtraMode mode;
|
||||
final URI url;
|
||||
|
||||
ExtraPropsFile(String fileName, URI url, Path path, ExtraMode mode)
|
||||
throws IOException {
|
||||
super(fileName, path);
|
||||
this.url = url;
|
||||
this.mode = mode;
|
||||
if (mode == ExtraMode.PATH_REL) {
|
||||
this.displayPath = CWD.relativize(path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addIncludeDefinition(Include include) {
|
||||
if (includes.isEmpty()) {
|
||||
String propName = "props.fileName";
|
||||
systemProps.put(propName, include.propsFile.fileName);
|
||||
include = Include.of(include.propsFile,
|
||||
include.value.replace(include.propsFile.fileName,
|
||||
"${props.none}${" + propName + "}"));
|
||||
}
|
||||
include.propsFile.markAsIncludedFromExtra();
|
||||
super.addIncludeDefinition(include);
|
||||
}
|
||||
|
||||
String getSysPropValue() {
|
||||
return switch (mode) {
|
||||
case HTTP_SERVED -> url.toString();
|
||||
case FILE_URI -> path.toUri().toString();
|
||||
case RAW_FILE_URI1 -> "file:" + path;
|
||||
case RAW_FILE_URI2 ->
|
||||
"file://" + (path.startsWith("/") ? "" : "/") + path;
|
||||
case PATH_ABS, PATH_REL -> displayPath.toString();
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, String> getSystemProperties() {
|
||||
return Collections.unmodifiableMap(systemProps);
|
||||
}
|
||||
}
|
||||
|
||||
final class FilesManager implements Closeable {
|
||||
private static final Path ROOT_DIR = Path.of(
|
||||
ExtraFileAndIncludes.class.getSimpleName()).toAbsolutePath();
|
||||
private static final Path PROPS_DIR = ROOT_DIR.resolve("properties");
|
||||
private static final Path JDK_DIR = ROOT_DIR.resolve("jdk");
|
||||
private static final Path MASTER_FILE =
|
||||
JDK_DIR.resolve("conf/security/java.security");
|
||||
private static final Path MASTER_FILE_TEMPLATE =
|
||||
MASTER_FILE.resolveSibling("java.security.template");
|
||||
static final String JAVA_EXECUTABLE =
|
||||
JDK_DIR.resolve("bin/java").toString();
|
||||
static final String LAST_FILE_PROP_NAME = "last-file";
|
||||
static final String APPLIED_PROP_VALUE = "applied";
|
||||
|
||||
private final List<PropsFile> createdFiles;
|
||||
private final Set<String> fileNamesInUse;
|
||||
private final HttpServer httpServer;
|
||||
private final URI serverUri;
|
||||
private final long masterFileLines;
|
||||
|
||||
FilesManager() throws Exception {
|
||||
createdFiles = new ArrayList<>();
|
||||
fileNamesInUse = new HashSet<>();
|
||||
httpServer = HttpServer.create(
|
||||
new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0);
|
||||
httpServer.createContext("/", this::handleRequest);
|
||||
InetSocketAddress address = httpServer.getAddress();
|
||||
httpServer.start();
|
||||
serverUri = new URI("http", null, address.getHostString(),
|
||||
address.getPort(), null, null, null);
|
||||
copyJDK();
|
||||
try (Stream<String> s = Files.lines(MASTER_FILE_TEMPLATE)) {
|
||||
masterFileLines = s.count();
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyJDK() throws Exception {
|
||||
Path testJDK = Path.of(Objects.requireNonNull(
|
||||
System.getProperty("test.jdk"), "unspecified test.jdk"));
|
||||
if (!Files.exists(testJDK)) {
|
||||
throw new RuntimeException("test.jdk -> nonexistent JDK");
|
||||
}
|
||||
Files.createDirectories(JDK_DIR);
|
||||
try (Stream<Path> pathStream = Files.walk(testJDK)) {
|
||||
pathStream.skip(1).forEach((Path file) -> {
|
||||
try {
|
||||
Files.copy(file, JDK_DIR.resolve(testJDK.relativize(file)),
|
||||
StandardCopyOption.COPY_ATTRIBUTES);
|
||||
} catch (IOException ioe) {
|
||||
throw new UncheckedIOException(ioe);
|
||||
}
|
||||
});
|
||||
}
|
||||
Files.move(MASTER_FILE, MASTER_FILE_TEMPLATE);
|
||||
}
|
||||
|
||||
private void handleRequest(HttpExchange x) throws IOException {
|
||||
String rawPath = x.getRequestURI().getRawPath();
|
||||
Path f = ROOT_DIR.resolve(x.getRequestURI().getPath().substring(1));
|
||||
int statusCode;
|
||||
byte[] responseBody;
|
||||
// Check for unescaped space, unresolved parent or backward slash.
|
||||
if (rawPath.matches("^.*( |(\\.|%2[Ee]){2}|\\\\|%5[Cc]).*$")) {
|
||||
statusCode = HttpURLConnection.HTTP_BAD_REQUEST;
|
||||
responseBody = new byte[0];
|
||||
} else if (Files.isRegularFile(f)) {
|
||||
x.getResponseHeaders().add("Content-type", "text/plain");
|
||||
statusCode = HttpURLConnection.HTTP_OK;
|
||||
responseBody = Files.readAllBytes(f);
|
||||
} else {
|
||||
statusCode = HttpURLConnection.HTTP_NOT_FOUND;
|
||||
responseBody = new byte[0];
|
||||
}
|
||||
System.out.println("[" + Instant.now() + "] " +
|
||||
getClass().getSimpleName() + ": " +
|
||||
x.getRequestMethod() + " " + rawPath + " -> " +
|
||||
statusCode + " (" + responseBody.length + " bytes)");
|
||||
try (OutputStream responseStream = x.getResponseBody()) {
|
||||
x.sendResponseHeaders(statusCode, responseBody.length);
|
||||
responseStream.write(responseBody);
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface PropsFileBuilder {
|
||||
PropsFile build(String fileName, Path path) throws IOException;
|
||||
}
|
||||
|
||||
private PropsFile newFile(Path path, PropsFileBuilder builder)
|
||||
throws IOException {
|
||||
String fileName = path.getFileName().toString();
|
||||
if (!fileNamesInUse.add(fileName)) {
|
||||
// Names must be unique in order for the special
|
||||
// property <fileName>=<APPLIED_PROP_VALUE> to work.
|
||||
throw new RuntimeException(fileName + " is repeated");
|
||||
}
|
||||
Files.createDirectories(path.getParent());
|
||||
PropsFile propsFile = builder.build(fileName, path);
|
||||
propsFile.addComment("Property to determine if this properties file " +
|
||||
"was parsed and not overwritten:");
|
||||
propsFile.addRawProperty(fileName, APPLIED_PROP_VALUE);
|
||||
propsFile.addComment(ExtraFileAndIncludes.SEPARATOR_THIN);
|
||||
propsFile.addComment("Property to be overwritten by every properties " +
|
||||
"file (master, extra or included):");
|
||||
propsFile.addRawProperty(LAST_FILE_PROP_NAME, fileName);
|
||||
propsFile.addComment(ExtraFileAndIncludes.SEPARATOR_THIN);
|
||||
createdFiles.add(propsFile);
|
||||
return propsFile;
|
||||
}
|
||||
|
||||
PropsFile newFile(String relPathStr) throws IOException {
|
||||
return newFile(PROPS_DIR.resolve(relPathStr), PropsFile::new);
|
||||
}
|
||||
|
||||
PropsFile newMasterFile() throws IOException {
|
||||
Files.copy(MASTER_FILE_TEMPLATE, MASTER_FILE);
|
||||
return newFile(MASTER_FILE, PropsFile::new);
|
||||
}
|
||||
|
||||
ExtraPropsFile newExtraFile(ExtraMode mode) throws IOException {
|
||||
return newExtraFile("extra.properties", mode);
|
||||
}
|
||||
|
||||
ExtraPropsFile newExtraFile(String extraFileName, ExtraMode mode)
|
||||
throws IOException {
|
||||
return (ExtraPropsFile) newFile(PROPS_DIR.resolve(extraFileName),
|
||||
(fileName, path) -> {
|
||||
URI uri = serverUri.resolve(ParseUtil.encodePath(
|
||||
ROOT_DIR.relativize(path).toString()));
|
||||
return new ExtraPropsFile(fileName, uri, path, mode);
|
||||
});
|
||||
}
|
||||
|
||||
void reportCreatedFiles() throws IOException {
|
||||
for (PropsFile propsFile : createdFiles) {
|
||||
System.err.println();
|
||||
System.err.println(propsFile.path.toString());
|
||||
System.err.println(ExtraFileAndIncludes.SEPARATOR_THIN.repeat(3));
|
||||
try (Stream<String> lines = Files.lines(propsFile.path)) {
|
||||
long lineNumber = 1L;
|
||||
Iterator<String> it = lines.iterator();
|
||||
while (it.hasNext()) {
|
||||
String line = it.next();
|
||||
if (!propsFile.path.equals(MASTER_FILE) ||
|
||||
lineNumber > masterFileLines) {
|
||||
System.err.println(line);
|
||||
}
|
||||
lineNumber++;
|
||||
}
|
||||
}
|
||||
System.err.println();
|
||||
}
|
||||
}
|
||||
|
||||
void clear() throws IOException {
|
||||
if (!createdFiles.isEmpty()) {
|
||||
for (PropsFile propsFile : createdFiles) {
|
||||
propsFile.close();
|
||||
Files.delete(propsFile.path);
|
||||
}
|
||||
FileUtils.deleteFileTreeUnchecked(PROPS_DIR);
|
||||
createdFiles.clear();
|
||||
fileNamesInUse.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
clear();
|
||||
httpServer.stop(0);
|
||||
FileUtils.deleteFileTreeUnchecked(ROOT_DIR);
|
||||
}
|
||||
}
|
||||
|
||||
final class Executor {
|
||||
static final String RUNNER_ARG = "runner";
|
||||
static final String INITIAL_PROP_LOG_MSG = "Initial security property: ";
|
||||
private static final String OVERRIDING_LOG_MSG =
|
||||
"overriding other security properties files!";
|
||||
private static final String[] ALWAYS_UNEXPECTED_LOG_MSGS = {
|
||||
"java.lang.AssertionError",
|
||||
INITIAL_PROP_LOG_MSG + "postInitTest=shouldNotRecord",
|
||||
INITIAL_PROP_LOG_MSG + "include=",
|
||||
};
|
||||
private static final String JAVA_SEC_PROPS = "java.security.properties";
|
||||
private static final String CLASS_PATH = Objects.requireNonNull(
|
||||
System.getProperty("test.classes"), "unspecified test.classes");
|
||||
private static final String DEBUG_ARG =
|
||||
"-Xrunjdwp:transport=dt_socket,address=localhost:8000,suspend=y";
|
||||
private final Map<String, String> systemProps = new LinkedHashMap<>(
|
||||
Map.of("java.security.debug", "all", "javax.net.debug", "all",
|
||||
// Ensure we get UTF-8 debug outputs in Windows:
|
||||
"stderr.encoding", "UTF-8", "stdout.encoding", "UTF-8"));
|
||||
private final List<String> jvmArgs = new ArrayList<>(
|
||||
List.of(FilesManager.JAVA_EXECUTABLE, "-enablesystemassertions",
|
||||
// Uncomment DEBUG_ARG to debug test-launched JVMs:
|
||||
"-classpath", CLASS_PATH//, DEBUG_ARG
|
||||
));
|
||||
private PropsFile masterPropsFile;
|
||||
private ExtraPropsFile extraPropsFile;
|
||||
private boolean expectedOverrideAll = false;
|
||||
private OutputAnalyzer oa;
|
||||
|
||||
static void run(Method m, FilesManager filesMgr) throws Exception {
|
||||
try {
|
||||
m.invoke(null, new Executor(), filesMgr);
|
||||
} catch (Throwable e) {
|
||||
filesMgr.reportCreatedFiles();
|
||||
throw e;
|
||||
} finally {
|
||||
filesMgr.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void addSystemProp(String key, String value) {
|
||||
systemProps.put(key, value);
|
||||
}
|
||||
|
||||
private void setRawExtraFile(String extraFile, boolean overrideAll) {
|
||||
addSystemProp(JAVA_SEC_PROPS, (overrideAll ? "=" : "") + extraFile);
|
||||
}
|
||||
|
||||
void setMasterFile(PropsFile masterPropsFile) {
|
||||
this.masterPropsFile = masterPropsFile;
|
||||
}
|
||||
|
||||
void setExtraFile(ExtraPropsFile extraPropsFile, boolean overrideAll) {
|
||||
this.extraPropsFile = extraPropsFile;
|
||||
expectedOverrideAll = overrideAll;
|
||||
setRawExtraFile(extraPropsFile.getSysPropValue(), overrideAll);
|
||||
}
|
||||
|
||||
void setIgnoredExtraFile(String extraPropsFile, boolean overrideAll) {
|
||||
setRawExtraFile(extraPropsFile, overrideAll);
|
||||
expectedOverrideAll = false;
|
||||
}
|
||||
|
||||
void addJvmArg(String arg) {
|
||||
jvmArgs.add(arg);
|
||||
}
|
||||
|
||||
private void execute(boolean successExpected) throws Exception {
|
||||
List<String> command = new ArrayList<>(jvmArgs);
|
||||
Collections.addAll(command, Utils.getTestJavaOpts());
|
||||
addSystemPropertiesAsJvmArgs(command);
|
||||
command.add(ExtraFileAndIncludes.class.getSimpleName());
|
||||
command.add(RUNNER_ARG);
|
||||
oa = ProcessTools.executeProcess(new ProcessBuilder(command));
|
||||
oa.shouldHaveExitValue(successExpected ? 0 : 1);
|
||||
for (String output : ALWAYS_UNEXPECTED_LOG_MSGS) {
|
||||
oa.shouldNotContain(output);
|
||||
}
|
||||
}
|
||||
|
||||
private void addSystemPropertiesAsJvmArgs(List<String> command) {
|
||||
Map<String, String> allSystemProps = new LinkedHashMap<>(systemProps);
|
||||
if (extraPropsFile != null) {
|
||||
allSystemProps.putAll(extraPropsFile.getSystemProperties());
|
||||
}
|
||||
for (Map.Entry<String, String> e : allSystemProps.entrySet()) {
|
||||
command.add("-D" + e.getKey() + "=" + e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
void assertSuccess() throws Exception {
|
||||
execute(true);
|
||||
|
||||
// Ensure every file was processed by checking a unique property used as
|
||||
// a flag. Each file defines <fileName>=applied.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// file0
|
||||
// ---------------
|
||||
// file0=applied
|
||||
// include file1
|
||||
//
|
||||
// file1
|
||||
// ---------------
|
||||
// file1=applied
|
||||
//
|
||||
// The assertion would be file0 == applied AND file1 == applied.
|
||||
//
|
||||
if (extraPropsFile != null) {
|
||||
extraPropsFile.assertApplied(oa);
|
||||
}
|
||||
if (expectedOverrideAll) {
|
||||
// When overriding with an extra file, check that neither
|
||||
// the master file nor its includes are visible.
|
||||
oa.shouldContain(OVERRIDING_LOG_MSG);
|
||||
masterPropsFile.assertWasOverwritten(oa);
|
||||
} else {
|
||||
oa.shouldNotContain(OVERRIDING_LOG_MSG);
|
||||
masterPropsFile.assertApplied(oa);
|
||||
}
|
||||
|
||||
// Ensure the last included file overwrote a fixed property. Each file
|
||||
// defines last-file=<fileName>.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// file0
|
||||
// ---------------
|
||||
// last-file=file0
|
||||
// include file1
|
||||
//
|
||||
// file1
|
||||
// ---------------
|
||||
// last-file=file1
|
||||
//
|
||||
// The assertion would be last-file == file1.
|
||||
//
|
||||
PropsFile lastFile = (extraPropsFile == null ?
|
||||
masterPropsFile : extraPropsFile).getLastFile();
|
||||
oa.shouldContain(FilesManager.LAST_FILE_PROP_NAME + "=" +
|
||||
lastFile.fileName);
|
||||
oa.stdoutShouldContain(FilesManager.LAST_FILE_PROP_NAME + ": " +
|
||||
lastFile.fileName);
|
||||
}
|
||||
|
||||
void assertError(String message) throws Exception {
|
||||
execute(false);
|
||||
oa.shouldContain(message);
|
||||
}
|
||||
|
||||
OutputAnalyzer getOutputAnalyzer() {
|
||||
return oa;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2026, Red Hat, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Ensures the java executable is able to load extra security
|
||||
* properties files from anonymous files and pipes.
|
||||
* @bug 8352728
|
||||
* @requires os.family == "linux"
|
||||
* @modules java.base/java.io:+open
|
||||
* @library /test/lib
|
||||
* @run main LinuxAnonymousFiles
|
||||
*/
|
||||
|
||||
public class LinuxAnonymousFiles {
|
||||
private static final String TEST_PROP = "property.name=PROPERTY_VALUE";
|
||||
|
||||
private static final class AnonymousFile implements AutoCloseable {
|
||||
public final Path fdPath;
|
||||
private final FileInputStream fis;
|
||||
|
||||
private AnonymousFile(CharSequence content) throws Exception {
|
||||
Path tmp = Files.createTempFile("anonymous-file-", "");
|
||||
Files.writeString(tmp, content + System.lineSeparator());
|
||||
fis = new FileInputStream(tmp.toFile());
|
||||
Files.delete(tmp);
|
||||
// Now the file is regular but anonymous, and will be unlinked
|
||||
// when we close the last file descriptor referring to it. The
|
||||
// fis instance ensures we keep it alive until close() is invoked.
|
||||
Field field = FileDescriptor.class.getDeclaredField("fd");
|
||||
field.setAccessible(true);
|
||||
int fd = field.getInt(fis.getFD());
|
||||
fdPath = Path.of("/proc/self").toRealPath().resolve("fd/" + fd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
fis.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Path java = Path.of(System.getProperty("test.jdk"), "bin", "java");
|
||||
try (AnonymousFile af = new AnonymousFile("include /dev/stdin")) {
|
||||
ProcessTools.executeProcess(new ProcessBuilder(java.toString(),
|
||||
"-Djava.security.debug=properties",
|
||||
"-Djava.security.properties=" + af.fdPath,
|
||||
"-XshowSettings:security:properties", "-version"),
|
||||
TEST_PROP).shouldHaveExitValue(0).shouldContain(TEST_PROP);
|
||||
}
|
||||
System.out.println("TEST PASS - OK");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2026, Red Hat, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.util.FileUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.AclEntry;
|
||||
import java.nio.file.attribute.AclEntryType;
|
||||
import java.nio.file.attribute.AclFileAttributeView;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Ensures java.security is loadable in Windows, even when the user
|
||||
* does not have permissions on one of the parent directories.
|
||||
* @bug 8352728
|
||||
* @requires os.family == "windows"
|
||||
* @library /test/lib
|
||||
* @run main WindowsParentDirPermissions
|
||||
*/
|
||||
|
||||
public class WindowsParentDirPermissions {
|
||||
private static AutoCloseable restrictedAcl(Path path) throws IOException {
|
||||
AclFileAttributeView view =
|
||||
Files.getFileAttributeView(path, AclFileAttributeView.class);
|
||||
List<AclEntry> originalAcl = List.copyOf(view.getAcl());
|
||||
view.setAcl(List.of(AclEntry.newBuilder().setType(AclEntryType.DENY)
|
||||
.setPrincipal(Files.getOwner(path)).build()));
|
||||
return () -> view.setAcl(originalAcl);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Path temp = Files.createTempDirectory("JDK-8352728-tmp-");
|
||||
try (AutoCloseable a1 = () -> FileUtils.deleteFileTreeUnchecked(temp)) {
|
||||
// Copy the jdk to a different directory
|
||||
Path originalJdk = Path.of(System.getProperty("test.jdk"));
|
||||
Path jdk = temp.resolve("jdk-parent-dir", "jdk");
|
||||
Files.createDirectories(jdk);
|
||||
FileUtils.copyDirectory(originalJdk, jdk);
|
||||
|
||||
// Remove current user permissions from jdk-parent-dir
|
||||
try (AutoCloseable a2 = restrictedAcl(jdk.getParent())) {
|
||||
// Make sure the permissions are affecting the current user
|
||||
try {
|
||||
jdk.toRealPath();
|
||||
throw new jtreg.SkippedException("Must run non-elevated!");
|
||||
} catch (IOException expected) { }
|
||||
|
||||
// Execute the copied jdk, ensuring java.security.Security is
|
||||
// loaded (i.e. use -XshowSettings:security:properties)
|
||||
ProcessTools.executeProcess(new ProcessBuilder(
|
||||
List.of(jdk.resolve("bin", "java.exe").toString(),
|
||||
"-Djava.security.debug=properties",
|
||||
"-XshowSettings:security:properties",
|
||||
"-version"))).shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
||||
System.out.println("TEST PASS - OK");
|
||||
}
|
||||
}
|
||||
149
test/jdk/java/security/Security/SynchronizedAccess.java
Normal file
149
test/jdk/java/security/Security/SynchronizedAccess.java
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2025, 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 4162583 7054918 8130181 8028127
|
||||
* @library /test/lib
|
||||
* @summary Make sure Provider api implementations are synchronized properly
|
||||
*/
|
||||
|
||||
import java.security.*;
|
||||
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.security.ProvidersSnapshot;
|
||||
|
||||
public class SynchronizedAccess {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ProvidersSnapshot snapshot = ProvidersSnapshot.create();
|
||||
try {
|
||||
main0(args);
|
||||
} finally {
|
||||
snapshot.restore();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main0(String[] args) throws Exception {
|
||||
var providersCountBefore = Security.getProviders().length;
|
||||
AccessorThread[] acc = new AccessorThread[200];
|
||||
for (int i = 0; i < acc.length; i++) {
|
||||
acc[i] = new AccessorThread("thread" + i);
|
||||
}
|
||||
for (int i = 0; i < acc.length; i++) {
|
||||
acc[i].start();
|
||||
}
|
||||
for (int i = 0; i < acc.length; i++) {
|
||||
acc[i].join();
|
||||
}
|
||||
var providersCountAfter = Security.getProviders().length;
|
||||
Asserts.assertEquals(providersCountBefore, providersCountAfter);
|
||||
}
|
||||
|
||||
static class AccessorThread extends Thread {
|
||||
|
||||
public AccessorThread(String str) {
|
||||
super(str);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
Provider[] provs = new Provider[10];
|
||||
for (int i = 0; i < provs.length; i++) {
|
||||
provs[i] = new MyProvider("name" + i, "1", "test");
|
||||
}
|
||||
|
||||
int rounds = 20;
|
||||
while (rounds-- > 0) {
|
||||
for (int i = 0; i < provs.length; i++) {
|
||||
// Might install (>=0) or not (-1) if already installed
|
||||
Security.addProvider(provs[i]);
|
||||
Thread.yield();
|
||||
}
|
||||
|
||||
try {
|
||||
Signature.getInstance("sigalg");
|
||||
Thread.yield();
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
// All providers may have been deregistered. Ok.
|
||||
}
|
||||
|
||||
for (int i = 0; i < provs.length; i++) {
|
||||
// Might or might not remove (silent return)
|
||||
Security.removeProvider("name" + i);
|
||||
Thread.yield();
|
||||
}
|
||||
} // while
|
||||
}
|
||||
|
||||
public static final class MyProvider extends Provider {
|
||||
public MyProvider(String name, String version, String info) {
|
||||
super(name, version, info);
|
||||
put("Signature.sigalg", SigImpl.class.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SigImpl extends Signature {
|
||||
|
||||
public SigImpl() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void engineInitVerify(PublicKey publicKey) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void engineInitSign(PrivateKey privateKey) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void engineUpdate(byte b) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void engineUpdate(byte[] b, int off, int len) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] engineSign() {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean engineVerify(byte[] sigBytes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void engineSetParameter(String param, Object value)
|
||||
throws InvalidParameterException {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object engineGetParameter(String param)
|
||||
throws InvalidParameterException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 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 4208414 8130181
|
||||
* @summary Providers should be removed "by-identity" - not "by-value"
|
||||
*/
|
||||
|
||||
import java.security.*;
|
||||
|
||||
public class RemoveProviderByIdentity {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String PROVIDER_NAME = "myprovider";
|
||||
|
||||
Security.addProvider(new MyProvider(PROVIDER_NAME, "1", "test"));
|
||||
if (Security.getProvider(PROVIDER_NAME) == null)
|
||||
throw new Exception("provider not registered");
|
||||
|
||||
Security.removeProvider(PROVIDER_NAME);
|
||||
if (Security.getProvider(PROVIDER_NAME) != null)
|
||||
throw new Exception("provider not removed");
|
||||
}
|
||||
}
|
||||
|
||||
class MyProvider extends Provider {
|
||||
public MyProvider(String name, String version, String info) {
|
||||
super(name, version, info);
|
||||
put("Signature.sigalg", "sigimpl");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2025, 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 4963416 7054918
|
||||
* @library /test/lib
|
||||
* @summary make sure removeProvider() always works correctly
|
||||
* @author Andreas Sterbenz
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import java.security.*;
|
||||
import jdk.test.lib.security.ProvidersSnapshot;
|
||||
|
||||
public class RemoveProviders {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ProvidersSnapshot snapshot = ProvidersSnapshot.create();
|
||||
try {
|
||||
main0(args);
|
||||
} finally {
|
||||
snapshot.restore();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main0(String[] args) throws Exception {
|
||||
Provider[] providers = Security.getProviders();
|
||||
System.out.println("Providers: " + Arrays.asList(providers));
|
||||
|
||||
// remove each provider and add it back in at the end of the list
|
||||
for (int i = 0; i < providers.length; i++) {
|
||||
Provider p = providers[i];
|
||||
String name = p.getName();
|
||||
Security.removeProvider(name);
|
||||
if (Security.getProvider(name) != null) {
|
||||
throw new Exception("Provider not removed: " + name);
|
||||
}
|
||||
Security.addProvider(p);
|
||||
}
|
||||
if (Arrays.equals(providers, Security.getProviders()) == false) {
|
||||
throw new Exception("Provider mismatch: " + Arrays.asList(Security.getProviders()));
|
||||
}
|
||||
|
||||
// remove non-existing provider
|
||||
Security.removeProvider("foo");
|
||||
if (Arrays.equals(providers, Security.getProviders()) == false) {
|
||||
throw new Exception("Provider mismatch: " + Arrays.asList(Security.getProviders()));
|
||||
}
|
||||
|
||||
// remove from the middle of the list
|
||||
Security.removeProvider("SunJCE");
|
||||
if (Security.getProvider("SunJCE") != null) {
|
||||
throw new Exception("not removed");
|
||||
}
|
||||
|
||||
System.out.println("Done.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 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 4420687
|
||||
* @summary Make sure that a removed provider won't be acceessable.
|
||||
* @run main/othervm RemoveStaticProvider
|
||||
*/
|
||||
import java.security.*;
|
||||
import javax.crypto.*;
|
||||
|
||||
public class RemoveStaticProvider {
|
||||
|
||||
public static void main(String argv[]) throws Exception {
|
||||
Security.removeProvider("SunJCE");
|
||||
try {
|
||||
KeyAgreement ka = KeyAgreement.getInstance("DH", "SunJCE");
|
||||
throw new Exception("Hmm... didn't get expected exception!");
|
||||
} catch (java.security.NoSuchProviderException nsa){
|
||||
System.out.println("Passed -- as expected: " + nsa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* precompiled
|
||||
**/
|
||||
|
||||
import java.security.*;
|
||||
import java.security.cert.*;
|
||||
|
||||
public class DynSignedProvFirst {
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
Provider p = new com.sun.exp.provider.EXP();
|
||||
Security.insertProviderAt(p, 1);
|
||||
|
||||
Object[] signers = p.getClass().getSigners();
|
||||
if (signers == null || signers.length <= 0) {
|
||||
throw new SecurityException("Test Failed");
|
||||
} else {
|
||||
for (int i = 0; i < signers.length; i++) {
|
||||
System.out.println("signer [" + i + "] = " + signers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
MessageDigest md = MessageDigest.getInstance("SHA1");
|
||||
System.out.println("test passed");
|
||||
}
|
||||
}
|
||||
94
test/jdk/java/security/Security/signedfirst/DynStatic.java
Normal file
94
test/jdk/java/security/Security/signedfirst/DynStatic.java
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 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 4504355 4744260
|
||||
* @summary problems if signed crypto provider is the most preferred provider
|
||||
* @modules java.base/sun.security.tools.keytool
|
||||
* jdk.jartool/sun.security.tools.jarsigner
|
||||
* @library /test/lib
|
||||
* @run main/othervm DynStatic
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import jdk.test.lib.compiler.CompilerUtils;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.util.JarUtils;
|
||||
|
||||
public class DynStatic {
|
||||
|
||||
private static final String TEST_SRC =
|
||||
Paths.get(System.getProperty("test.src")).toString();
|
||||
private static final Path TEST_CLASSES =
|
||||
Paths.get(System.getProperty("test.classes"));
|
||||
|
||||
private static final Path EXP_SRC_DIR = Paths.get(TEST_SRC, "com");
|
||||
private static final Path EXP_DEST_DIR = Paths.get("build");
|
||||
private static final Path DYN_SRC =
|
||||
Paths.get(TEST_SRC, "DynSignedProvFirst.java");
|
||||
private static final Path STATIC_SRC =
|
||||
Paths.get(TEST_SRC, "StaticSignedProvFirst.java");
|
||||
private static final Path STATIC_PROPS =
|
||||
Paths.get(TEST_SRC, "Static.props");
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
// Compile the provider
|
||||
CompilerUtils.compile(EXP_SRC_DIR, EXP_DEST_DIR);
|
||||
|
||||
// Create a jar file containing the provider
|
||||
JarUtils.createJarFile(Path.of("exp.jar"), EXP_DEST_DIR, "com");
|
||||
|
||||
// Create a keystore
|
||||
sun.security.tools.keytool.Main.main(
|
||||
("-genkeypair -dname CN=Signer -keystore exp.ks -storepass "
|
||||
+ "changeit -keypass changeit -keyalg rsa").split(" "));
|
||||
|
||||
// Sign jar
|
||||
sun.security.tools.jarsigner.Main.main(
|
||||
"-storepass changeit -keystore exp.ks exp.jar mykey"
|
||||
.split(" "));
|
||||
|
||||
// Compile the DynSignedProvFirst test program
|
||||
CompilerUtils.compile(DYN_SRC, TEST_CLASSES, "-classpath", "exp.jar");
|
||||
|
||||
// Run the DynSignedProvFirst test program
|
||||
ProcessTools.executeTestJava("-classpath",
|
||||
TEST_CLASSES.toString() + File.pathSeparator + "exp.jar",
|
||||
"DynSignedProvFirst")
|
||||
.shouldContain("test passed");
|
||||
|
||||
// Compile the StaticSignedProvFirst test program
|
||||
CompilerUtils.compile(STATIC_SRC, TEST_CLASSES, "-classpath", "exp.jar");
|
||||
|
||||
// Run the StaticSignedProvFirst test program
|
||||
ProcessTools.executeTestJava("-classpath",
|
||||
TEST_CLASSES.toString() + File.pathSeparator + "exp.jar",
|
||||
"-Djava.security.properties=" + STATIC_PROPS.toUri(),
|
||||
"StaticSignedProvFirst")
|
||||
.shouldContain("test passed");
|
||||
}
|
||||
}
|
||||
8
test/jdk/java/security/Security/signedfirst/Static.props
Normal file
8
test/jdk/java/security/Security/signedfirst/Static.props
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
security.provider.1=com.sun.exp.provider.EXP
|
||||
security.provider.2=sun.security.provider.Sun
|
||||
security.provider.3=sun.security.rsa.SunRsaSign
|
||||
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
|
||||
security.provider.5=com.sun.crypto.provider.SunJCE
|
||||
security.provider.6=sun.security.jgss.SunProvider
|
||||
security.provider.7=com.sun.security.sasl.Provider
|
||||
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2003, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* precompiled
|
||||
**/
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import java.security.*;
|
||||
import java.security.cert.*;
|
||||
|
||||
public class StaticSignedProvFirst {
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
Class clazz = Class.forName("com.sun.exp.provider.EXP");
|
||||
|
||||
Provider[] providers = Security.getProviders();
|
||||
System.out.println("Providers: " + Arrays.asList(providers));
|
||||
if (providers[0].getName().equals("EXP") == false) {
|
||||
throw new Exception("EXP provider not loaded!");
|
||||
}
|
||||
Object[] signers = providers[0].getClass().getSigners();
|
||||
if (signers == null || signers.length <= 0) {
|
||||
throw new SecurityException("Test Failed - provider not signed");
|
||||
} else {
|
||||
for (int i = 0; i < signers.length; i++) {
|
||||
System.out.println("signer [" + i + "] = " + signers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
MessageDigest md = MessageDigest.getInstance("SHA1", "EXP");
|
||||
|
||||
System.out.println("test passed");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
package com.sun.exp.provider;
|
||||
|
||||
import java.security.Provider;
|
||||
|
||||
public class EXP extends Provider {
|
||||
|
||||
public EXP() {
|
||||
super("EXP", 0.0d, "Test provider");
|
||||
put("MessageDigest.SHA1", "com.sun.exp.provider.SHA");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 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.
|
||||
*/
|
||||
|
||||
package com.sun.exp.provider;
|
||||
|
||||
import java.security.MessageDigestSpi;
|
||||
|
||||
public class SHA extends MessageDigestSpi {
|
||||
protected void engineReset() {}
|
||||
protected void engineUpdate(byte input) {}
|
||||
protected void engineUpdate(byte[] input, int offset, int len) {}
|
||||
protected byte[] engineDigest() { return null; }
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue