From 945f0381452531d86ac8c07f2d7c4d2c65acc2ca Mon Sep 17 00:00:00 2001 From: jovsteva Date: Wed, 25 Dec 2024 19:14:38 +0100 Subject: [PATCH] Parse java.security.properties file at run time. --- .../core/jdk/SecurityProvidersSupport.java | 11 ++++ .../svm/core/jdk/SecuritySubstitutions.java | 51 +++++++++++++++++++ .../svm/hosted/SecurityServicesFeature.java | 12 +++-- 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecurityProvidersSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecurityProvidersSupport.java index 20f81d06ebc4..8e314299c6b2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecurityProvidersSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecurityProvidersSupport.java @@ -33,6 +33,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.Set; import org.graalvm.nativeimage.ImageSingletons; @@ -69,6 +70,8 @@ public final class SecurityProvidersSupport { */ private final Map verifiedSecurityProviders = Collections.synchronizedMap(new HashMap<>()); + private Properties savedInitialSecurityProperties; + private Constructor sunECConstructor; @Platforms(Platform.HOSTED_ONLY.class) @@ -126,4 +129,12 @@ public Provider allocateSunECProvider() { throw VMError.shouldNotReachHere("The SunEC constructor is not present."); } } + + public void setSavedInitialSecurityProperties(Properties savedSecurityProperties) { + this.savedInitialSecurityProperties = savedSecurityProperties; + } + + public Properties getSavedInitialSecurityProperties() { + return savedInitialSecurityProperties; + } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecuritySubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecuritySubstitutions.java index e36b1d1ad07b..50c1017dd610 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecuritySubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecuritySubstitutions.java @@ -26,6 +26,7 @@ import static com.oracle.svm.core.snippets.KnownIntrinsics.readCallerStackPointer; +import java.io.File; import java.lang.reflect.Constructor; import java.net.URL; import java.security.AccessControlContext; @@ -42,6 +43,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Properties; import java.util.WeakHashMap; import java.util.function.BooleanSupplier; import java.util.function.Predicate; @@ -71,6 +73,7 @@ import jdk.graal.compiler.core.common.SuppressFBWarnings; import jdk.graal.compiler.serviceprovider.JavaVersionUtil; +import sun.security.util.Debug; import sun.security.util.SecurityConstants; /* @@ -220,6 +223,54 @@ final class Target_java_security_Provider_Service { private Object constructorCache; } +@TargetClass(value = java.security.Security.class) +final class Target_java_security_Security { + @Alias // + @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias) // + static Properties props; + + @Alias // + private static Properties initialSecurityProperties; + + @Alias // + private static Debug sdebug; + + @Substitute + @TargetElement(onlyWith = JDK21OrEarlier.class) + private static void initialize() { + props = SecurityProvidersSupport.singleton().getSavedInitialSecurityProperties(); + boolean overrideAll = false; + + if ("true".equalsIgnoreCase(props.getProperty("security.overridePropertiesFile"))) { + String extraPropFile = System.getProperty("java.security.properties"); + if (extraPropFile != null && extraPropFile.startsWith("=")) { + overrideAll = true; + extraPropFile = extraPropFile.substring(1); + } + loadProps(null, extraPropFile, overrideAll); + } + initialSecurityProperties = (Properties) props.clone(); + if (sdebug != null) { + for (String key : props.stringPropertyNames()) { + sdebug.println("Initial security property: " + key + "=" + props.getProperty(key)); + } + } + } + + @Alias + @TargetElement(onlyWith = JDK21OrEarlier.class) + private static native boolean loadProps(File masterFile, String extraPropFile, boolean overrideAll); +} + +@TargetClass(value = java.security.Security.class, innerClass = "SecPropLoader", onlyWith = JDKLatest.class) +final class Target_java_security_Security_SecPropLoader { + + @Substitute + private static void loadMaster() { + Target_java_security_Security.props = SecurityProvidersSupport.singleton().getSavedInitialSecurityProperties(); + } +} + class ServiceKeyProvider { static Object getNewServiceKey() { Class serviceKey = ReflectionUtil.lookupClass("java.security.Provider$ServiceKey"); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java index 36bcd747c495..5550b7f0e877 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java @@ -64,6 +64,7 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Properties; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiConsumer; @@ -109,6 +110,7 @@ import jdk.graal.compiler.options.Option; import jdk.graal.compiler.serviceprovider.JavaVersionUtil; +import jdk.internal.access.SharedSecrets; import sun.security.provider.NativePRNG; import sun.security.x509.OIDMap; @@ -229,13 +231,17 @@ public void duringSetup(DuringSetupAccess a) { SecurityProvidersSupport.singleton().setSunECConstructor(sunECConstructor); } + Properties securityProperties = SharedSecrets.getJavaSecurityPropertiesAccess().getInitialProperties(); + SecurityProvidersSupport.singleton().setSavedInitialSecurityProperties(securityProperties); + RuntimeClassInitializationSupport rci = ImageSingletons.lookup(RuntimeClassInitializationSupport.class); /* * Security providers will be initialized at run time because the class initialization - * simulation will determine that automatically. For the two classes below, however, we need - * to handle this explicitly because their packages are already marked for initialization at - * build time by JdkInitializationFeature#afterRegistration. + * simulation will determine that automatically. For the three classes below, however, we + * need to handle this explicitly because their packages are already marked for + * initialization at build time by JdkInitializationFeature#afterRegistration. */ + rci.initializeAtRunTime("java.security.Security", SECURITY_PROVIDERS_INITIALIZATION); rci.initializeAtRunTime("sun.security.jca.Providers", SECURITY_PROVIDERS_INITIALIZATION); rci.initializeAtRunTime("sun.security.provider.certpath.ldap.JdkLDAP", SECURITY_PROVIDERS_INITIALIZATION);