From 711bdb8684c549473e530fb4846d09960677a4fe Mon Sep 17 00:00:00 2001 From: Patrick Schmitt Date: Mon, 16 Dec 2024 09:14:03 +0100 Subject: [PATCH 1/2] Fix #2075 Slow startup because of low entropy for PRNG (#2318) * Fix hang-up due to blocking PRNG returned by SecureRandom.getInstanceStrong() Fixes #2075 (cherry picked from commit 4ef35171a40eb0db9fde4eaf0c444c9a0baa331f) Signed-off-by: Patrick Schmitt --- .../persistence/config/SystemProperties.java | 73 +++++++++++-------- .../internal/security/JCEEncryptor.java | 17 ++++- .../security/PrivilegedAccessHelper.java | 46 +++++------- 3 files changed, 72 insertions(+), 64 deletions(-) diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/config/SystemProperties.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/config/SystemProperties.java index ebd54be3a00..b6c5f2f3db1 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/config/SystemProperties.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/config/SystemProperties.java @@ -1,5 +1,6 @@ /* * Copyright (c) 1998, 2024 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024 Contributors to the Eclipse Foundation. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -23,7 +24,7 @@ * @author tware * */ -public class SystemProperties { +public final class SystemProperties { /** * Configures the factory class we use to produce instances of org.eclispe.persistence.jpa.Archive @@ -60,7 +61,7 @@ public class SystemProperties { * the lock acquisition and print it along with the identity map locks. This * should only be set if the thread that owns a lock is not 'stuck' but * still owns the lock when a normal printIdentityMapLocks is done. - * + *

* This can also be set in code statically through ConcurrencyManager.setShouldTrackStack(true) */ public static final String RECORD_STACK_ON_LOCK = "eclipselink.cache.record-stack-on-lock"; @@ -75,7 +76,7 @@ public class SystemProperties { /** * This system property can be set to override target server platform set by the Java EE container - * with the one either set in persistence.xml or auto detected. + * with the one either set in persistence.xml or auto-detected. */ public static final String ENFORCE_TARGET_SERVER = "eclipselink.target-server.enforce"; @@ -94,7 +95,7 @@ public class SystemProperties { public static final String CONVERSION_USE_DEFAULT_TIMEZONE = "org.eclipse.persistence.conversion.useDefaultTimeZoneForJavaTime"; /** - * This property can be set to false to enable UPDATE call to set + * This property can be set to {@code false} to enable UPDATE call to set * foreign key value in the target row in unidirectional 1-Many mapping * with not nullable FK. In previous versions of EclipseLink this was * the default behaviour. @@ -104,7 +105,7 @@ public class SystemProperties { /** * This system property in milliseconds can control thread management in org.eclipse.persistence.internal.helper.ConcurrencyManager. - * It control how much time loop wait before it try acquire lock for current thread again. It value is set above above 0 dead lock detection + * It controls how much time loop wait before it tries to acquire lock for current thread again. If the value is set above 0 deadlock detection * mechanism and related extended logging will be activated. * Default value is 0 (unit is ms). Allowed values are: long */ @@ -112,46 +113,46 @@ public class SystemProperties { /** * This system property in milliseconds can control thread management in org.eclipse.persistence.internal.helper.ConcurrencyManager. - * It control how much time ConcurrencyManager will wait before it will identify, that thread which builds new object/entity instance - * should be identified as a potential dead lock source. It leads into some additional log messages. + * It controls how much time ConcurrencyManager will wait before it will identify, that thread which builds new object/entity instance + * should be identified as a potential deadlock source. It leads into some additional log messages. * Default value is 0 (unit is ms). In this case extended logging is not active. Allowed values are: long */ public static final String CONCURRENCY_MANAGER_BUILD_OBJECT_COMPLETE_WAIT_TIME = "eclipselink.concurrency.manager.build.object.complete.waittime"; /** * This system property in milliseconds can control thread management in org.eclipse.persistence.internal.helper.ConcurrencyManager. - * It control how long we are willing to wait before firing up an exception + * It controls how long we are willing to wait before firing up an exception * Default value is 40000 (unit is ms). Allowed values are: long */ public static final String CONCURRENCY_MANAGER_MAX_SLEEP_TIME = "eclipselink.concurrency.manager.maxsleeptime"; /** * This system property in milliseconds can control thread management in org.eclipse.persistence.internal.helper.ConcurrencyManager and org.eclipse.persistence.internal.helper.ConcurrencyUtil. - * It control how frequently the tiny dump log message is created. + * It controls how frequently the tiny dump log message is created. * Default value is 40000 (unit is ms). Allowed values are: long */ public static final String CONCURRENCY_MANAGER_MAX_FREQUENCY_DUMP_TINY_MESSAGE = "eclipselink.concurrency.manager.maxfrequencytodumptinymessage"; /** * This system property in milliseconds can control thread management in org.eclipse.persistence.internal.helper.ConcurrencyManager and org.eclipse.persistence.internal.helper.ConcurrencyUtil. - * It control how frequently the massive dump log message is created. + * It controls how frequently the massive dump log message is created. * Default value is 60000 (unit is ms). Allowed values are: long */ public static final String CONCURRENCY_MANAGER_MAX_FREQUENCY_DUMP_MASSIVE_MESSAGE = "eclipselink.concurrency.manager.maxfrequencytodumpmassivemessage"; /** *

- * This property control (enable/disable) if InterruptedException fired when dead-lock diagnostic is enabled. + * This property control (enable/disable) if {@code InterruptedException} fired when dead-lock diagnostic is enabled. *

* Allowed Values (case sensitive String): *

*/ @@ -159,16 +160,16 @@ public class SystemProperties { /** *

- * This property control (enable/disable) if ConcurrencyException fired when dead-lock diagnostic is enabled. + * This property control (enable/disable) if {@code ConcurrencyException} fired when dead-lock diagnostic is enabled. *

* Allowed Values (case sensitive String): *

*/ @@ -180,8 +181,8 @@ public class SystemProperties { *

* Allowed Values (case sensitive String): *

*/ public static final String CONCURRENCY_MANAGER_ALLOW_STACK_TRACE_READ_LOCK = "eclipselink.concurrency.manager.allow.readlockstacktrace"; @@ -192,13 +193,13 @@ public class SystemProperties { *

* Object building see {@link org.eclipse.persistence.internal.descriptors.ObjectBuilder} could be one of the * primary sources pressure on concurrency manager. Most of the cache key acquisition and releasing is taking place during object building. - * Enable true this property to try reduce the likelihood of having dead locks is to allow less threads to start object + * Enable {@code true} this property to try reduce the likelihood of having dead locks is to allow less threads to start object * building in parallel. In this case there should be negative impact to the performance. * Note: Parallel access to the same entity/entity tree from different threads is not recommended technique in EclipseLink. * */ @@ -215,9 +216,9 @@ public class SystemProperties { * one-to-many relations of master detail being enriched with more details on this master). * Note: Parallel access to the same entity/entity tree from different threads is not recommended technique in EclipseLink. * */ @@ -226,8 +227,8 @@ public class SystemProperties { /** *

* This property control number of threads in semaphore in {@link org.eclipse.persistence.internal.descriptors.ObjectBuilder} - * If "eclipselink.concurrency.manager.object.building.semaphore" property is true default value is 10. Allowed values are: int - * If "eclipselink.concurrency.manager.object.building.semaphore" property is false (DEFAULT) number of threads is unlimited. + * If "eclipselink.concurrency.manager.object.building.semaphore" property is {@code true} default value is 10. Allowed values are: int + * If "eclipselink.concurrency.manager.object.building.semaphore" property is {@code false} (DEFAULT) number of threads is unlimited. *

*/ public static final String CONCURRENCY_MANAGER_OBJECT_BUILDING_NO_THREADS = "eclipselink.concurrency.manager.object.building.no.threads"; @@ -235,8 +236,8 @@ public class SystemProperties { /** *

* This property control number of threads in semaphore in {@link org.eclipse.persistence.internal.helper.WriteLockManager#acquireRequiredLocks} - * If "eclipselink.concurrency.manager.write.lock.manager.semaphore" property is true default value is 2. Allowed values are: int - * If "eclipselink.concurrency.manager.write.lock.manager.semaphore" property is false (DEFAULT) number of threads is unlimited. + * If "eclipselink.concurrency.manager.write.lock.manager.semaphore" property is {@code true} default value is 2. Allowed values are: int + * If "eclipselink.concurrency.manager.write.lock.manager.semaphore" property is {@code false} (DEFAULT) number of threads is unlimited. *

*/ public static final String CONCURRENCY_MANAGER_WRITE_LOCK_MANAGER_ACQUIRE_REQUIRED_LOCKS_NO_THREADS = "eclipselink.concurrency.manager.write.lock.manager.no.threads"; @@ -265,17 +266,25 @@ public class SystemProperties { *

* Allowed Values (case sensitive String): *

*/ public static final String ASM_SERVICE = "eclipselink.asm.service"; /** - * @deprecated This constructor will be marked private and the class final. It is not designed for extensibility. + *

+ * This property control the random number generator (RNG) used for password encryption. + *

+ * Allowed Values (case sensitive String): + *

*/ - @Deprecated(since = "4.0.3", forRemoval = true) - public SystemProperties() { + public static final String SECURITY_ENCRYPTOR_USE_STRONG_RANDOM_NUMBER_GENERATOR = "eclipselink.security.encryptor.use.strong.random.number.generator"; + + private SystemProperties() { // no instance please } } diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/security/JCEEncryptor.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/security/JCEEncryptor.java index 6397e556321..38e6b90165f 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/security/JCEEncryptor.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/security/JCEEncryptor.java @@ -1,5 +1,6 @@ /* * Copyright (c) 1998, 2024 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024 Contributors to the Eclipse Foundation. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -14,6 +15,7 @@ // Oracle - initial API and implementation from Oracle TopLink package org.eclipse.persistence.internal.security; +import org.eclipse.persistence.config.SystemProperties; import org.eclipse.persistence.exceptions.ConversionException; import org.eclipse.persistence.exceptions.ValidationException; import org.eclipse.persistence.internal.helper.Helper; @@ -124,10 +126,17 @@ private static SecretKey getAESGCMMultitasker() throws Exception { private static byte[] getIvGCM() { byte[] ivGCM = new byte[IV_GCM_LENGTH]; SecureRandom random = null; - try { - random = SecureRandom.getInstanceStrong(); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); + String useStrongRNG = PrivilegedAccessHelper.getSystemProperty(SystemProperties.SECURITY_ENCRYPTOR_USE_STRONG_RANDOM_NUMBER_GENERATOR); + if (useStrongRNG == null || useStrongRNG.equalsIgnoreCase("false")) { + random = new SecureRandom(); + } else if (useStrongRNG.equalsIgnoreCase("true")) { + try { + random = SecureRandom.getInstanceStrong(); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } else { + throw ValidationException.invalidBooleanValueForProperty(useStrongRNG, SystemProperties.SECURITY_ENCRYPTOR_USE_STRONG_RANDOM_NUMBER_GENERATOR); } random.nextBytes(ivGCM); return ivGCM; diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/security/PrivilegedAccessHelper.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/security/PrivilegedAccessHelper.java index d4508f9ed15..59edd0d08ac 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/security/PrivilegedAccessHelper.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/security/PrivilegedAccessHelper.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024 Contributors to the Eclipse Foundation. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -22,6 +23,16 @@ // - 254437: Added getSystemProperty methods and fixed line separator property. package org.eclipse.persistence.internal.security; +import org.eclipse.persistence.config.PersistenceUnitProperties; +import org.eclipse.persistence.config.SystemProperties; +import org.eclipse.persistence.internal.helper.Helper; +import org.eclipse.persistence.internal.helper.JavaVersion; +import org.eclipse.persistence.internal.localization.ExceptionLocalization; +import org.eclipse.persistence.logging.AbstractSessionLog; +import org.eclipse.persistence.logging.SessionLog; +import org.eclipse.persistence.platform.server.ServerPlatformBase; +import org.eclipse.persistence.platform.xml.XMLPlatformFactory; + import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -30,33 +41,21 @@ import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Set; -import org.eclipse.persistence.config.PersistenceUnitProperties; -import org.eclipse.persistence.config.SystemProperties; -import org.eclipse.persistence.internal.helper.Helper; -import org.eclipse.persistence.internal.helper.JavaVersion; -import org.eclipse.persistence.internal.localization.ExceptionLocalization; -import org.eclipse.persistence.logging.AbstractSessionLog; -import org.eclipse.persistence.logging.SessionLog; -import org.eclipse.persistence.platform.server.ServerPlatformBase; -import org.eclipse.persistence.platform.xml.XMLPlatformFactory; - /** * INTERNAL: * Privileged Access Helper provides a utility so all calls that require privileged access can use the same code. - * + *

* Do privileged blocks can be used with a security manager to grant a code base (eclipselink.jar) access to certain * Java operations such as reflection. Generally a security manager is not enabled in a JVM, so this is not an issue. * If a security manager is enabled, then either the application can be configured to have access to operations such as * reflection, or only EclipseLink can be given access. If only EclipseLink is desired to be given access then * do privileged must be enabled through the System property "eclipselink.security.usedoprivileged"=true. - * + *

* Note the usage of do privileged has major impacts on performance, so should normally be avoided. */ public class PrivilegedAccessHelper { @@ -65,7 +64,7 @@ public class PrivilegedAccessHelper { private static boolean shouldCheckPrivilegedAccess = true; private static boolean shouldUsePrivilegedAccess = false; - private final static String[] legalProperties = { "file.separator", "java.io.tmpdir", JavaVersion.VM_VERSION_PROPERTY, "line.separator", "path.separator", "user.dir", + private final static String[] legalProperties = { "java.io.tmpdir", JavaVersion.VM_VERSION_PROPERTY, "user.dir", "org.eclipse.persistence.fetchgroupmonitor", "org.eclipse.persistence.querymonitor", "SAP_J2EE_Engine_Version", PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML, PersistenceUnitProperties.JAVASE_DB_INTERACTION, PersistenceUnitProperties.LOGGING_FILE, PersistenceUnitProperties.LOGGING_LEVEL, @@ -75,12 +74,12 @@ public class PrivilegedAccessHelper { SystemProperties.CONCURRENCY_MANAGER_ACQUIRE_WAIT_TIME, SystemProperties.CONCURRENCY_MANAGER_BUILD_OBJECT_COMPLETE_WAIT_TIME, SystemProperties.CONCURRENCY_MANAGER_MAX_SLEEP_TIME, SystemProperties.CONCURRENCY_MANAGER_MAX_FREQUENCY_DUMP_TINY_MESSAGE, SystemProperties.CONCURRENCY_MANAGER_MAX_FREQUENCY_DUMP_MASSIVE_MESSAGE, SystemProperties.CONCURRENCY_MANAGER_ALLOW_INTERRUPTED_EXCEPTION, SystemProperties.CONCURRENCY_MANAGER_ALLOW_CONCURRENCY_EXCEPTION, SystemProperties.CONCURRENCY_MANAGER_ALLOW_STACK_TRACE_READ_LOCK, + SystemProperties.SECURITY_ENCRYPTOR_USE_STRONG_RANDOM_NUMBER_GENERATOR, ServerPlatformBase.JMX_REGISTER_RUN_MBEAN_PROPERTY, ServerPlatformBase.JMX_REGISTER_DEV_MBEAN_PROPERTY, XMLPlatformFactory.XML_PLATFORM_PROPERTY}; - private final static Set legalPropertiesSet = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(legalProperties))); + private final static Set legalPropertiesSet = Set.of(legalProperties); - private final static String[] exemptedProperties = { "line.separator" }; - private final static Set exemptedPropertiesSet = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(exemptedProperties))); + private static final Set exemptedPropertiesSet = Collections.emptySet(); private static final Map> primitiveClasses; @@ -671,15 +670,6 @@ public static boolean getSystemPropertyBoolean(final String key, final boolean d getSystemProperty(key, def ? TRUE_STRING : "")); } - /** - * INTERNAL: - * Get the line separator character. - * @return The {@link String} containing the platform-appropriate characters for line separator. - */ - public static String getLineSeparator() { - return getSystemProperty("line.separator"); - } - /** * Get the list of parameter types for a given method. Wrap the call in doPrivileged if necessary. * @param method The method to get the parameter types of From 712c00e6d91bae785a633b5516193c331ce1e0e1 Mon Sep 17 00:00:00 2001 From: Patrick Schmitt Date: Fri, 20 Dec 2024 12:33:35 +0100 Subject: [PATCH 2/2] add line.separator to legal properties Signed-off-by: Patrick Schmitt --- .../persistence/internal/security/PrivilegedAccessHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/security/PrivilegedAccessHelper.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/security/PrivilegedAccessHelper.java index 59edd0d08ac..7e52bed8e39 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/security/PrivilegedAccessHelper.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/security/PrivilegedAccessHelper.java @@ -64,7 +64,7 @@ public class PrivilegedAccessHelper { private static boolean shouldCheckPrivilegedAccess = true; private static boolean shouldUsePrivilegedAccess = false; - private final static String[] legalProperties = { "java.io.tmpdir", JavaVersion.VM_VERSION_PROPERTY, "user.dir", + private final static String[] legalProperties = { "line.separator", "java.io.tmpdir", JavaVersion.VM_VERSION_PROPERTY, "user.dir", "org.eclipse.persistence.fetchgroupmonitor", "org.eclipse.persistence.querymonitor", "SAP_J2EE_Engine_Version", PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML, PersistenceUnitProperties.JAVASE_DB_INTERACTION, PersistenceUnitProperties.LOGGING_FILE, PersistenceUnitProperties.LOGGING_LEVEL,