From aff1a8916a3c10bfc15f1cc61d3eb9add0294999 Mon Sep 17 00:00:00 2001 From: Tao Liu Date: Mon, 23 Sep 2024 11:23:37 -0400 Subject: [PATCH] Check RestrictedSecurity profile for errors This commit checks the misspelled properties and provider order numbers in RestrictedSecurity mode. If there is a misspelled property or the provider order numbers are not consecutive. The RestrictedSecurity mode initialization will stop and throw errors. Signed-off-by: Tao Liu --- .../internal/security/RestrictedSecurity.java | 57 ++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/closed/src/java.base/share/classes/openj9/internal/security/RestrictedSecurity.java b/closed/src/java.base/share/classes/openj9/internal/security/RestrictedSecurity.java index 470401ff76a..f8663d7db1f 100644 --- a/closed/src/java.base/share/classes/openj9/internal/security/RestrictedSecurity.java +++ b/closed/src/java.base/share/classes/openj9/internal/security/RestrictedSecurity.java @@ -35,10 +35,10 @@ import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.Deque; +import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -994,6 +994,9 @@ private static final class ProfileParser { // The java.security properties. private final Properties securityProps; + private final Set profileCheckPropertyNames; + private final Set profileCheckProviderNames; + /** * * @param id the restricted security custom profile ID @@ -1016,8 +1019,13 @@ private ProfileParser(String id, Properties props) { parsedProfiles = new HashSet<>(); + profileCheckPropertyNames = new HashSet<>(); + profileCheckProviderNames = new HashSet<>(); + // Initialize the properties. init(profileID); + + checkProfileCheck(profileID); } private RestrictedSecurityProperties getProperties() { @@ -1040,12 +1048,17 @@ private void init(String profileID) { printStackTraceAndExit(profileID + " has already been parsed. Potential infinite recursion."); } - String potentialExtendsProfileID = parseProperty(securityProps.getProperty(profileID + ".extends")); + loadProfileCheck(profileID); + + String profileExtends = profileID + ".extends"; + String potentialExtendsProfileID = parseProperty(securityProps.getProperty(profileExtends)); if (potentialExtendsProfileID != null) { // If profile extends another profile. if (debug != null) { debug.println("\t'" + profileID + "' extends '" + potentialExtendsProfileID + "'."); } + profileCheckPropertyNames.remove(profileExtends); + // Check if extended profile exists. String extendsProfileID = null; if (potentialExtendsProfileID.indexOf('.') != potentialExtendsProfileID.lastIndexOf('.')) { @@ -1098,6 +1111,7 @@ private void init(String profileID) { // Save info to be hashed and expected result to be checked later. profilesHashes.put(profileID, hashValue); profilesInfo.put(profileID, allInfo); + profileCheckPropertyNames.remove(hashProperty); } else if (!isFIPS1402Profile(profileID)) { // A hash is mandatory, but not for older 140-2 profiles. printStackTraceAndExit(profileID + " is a base profile, so a hash value is mandatory."); @@ -1134,6 +1148,7 @@ private void update(String profileExtensionId) { // Save info to be hashed and expected result to be checked later. profilesHashes.put(profileID, hashValue); profilesInfo.put(profileID, allInfo); + profileCheckPropertyNames.remove(hashProperty); } } catch (Exception e) { if (debug != null) { @@ -1254,6 +1269,7 @@ private void initProviders(String profileID, List allInfo) { allInfo.add(property + "=" + providerInfo); parseProvider(providerInfo, pNum, false); + profileCheckProviderNames.remove(property); } if (providers.isEmpty()) { @@ -1284,6 +1300,7 @@ private void updateProviders(String profileExtensionId, List allInfo) { removedProvider = true; break; } + profileCheckProviderNames.remove(property); } } @@ -1311,6 +1328,7 @@ private void updateProviders(String profileExtensionId, List allInfo) { allInfo.add(property + "=" + providerInfo); parseProvider(providerInfo, i, false); + profileCheckProviderNames.remove(property); } } @@ -1634,6 +1652,7 @@ private boolean setProperty(String property, String propertyKey, List al newValue = value; } profileProperties.put(property, newValue); + profileCheckPropertyNames.remove(propertyKey); return true; } if (debug != null) { @@ -1706,6 +1725,40 @@ private static void checkProviderFormat(String providerInfo, boolean update) { printStackTraceAndExit("Provider format is incorrect: " + providerInfo); } } + + private void loadProfileCheck(String profileID) { + Enumeration pNames = securityProps.propertyNames(); + String profileDot = profileID + '.'; + while (pNames.hasMoreElements()) { + String name = (String) pNames.nextElement(); + if (name.startsWith(profileDot)) { + if (name.contains(".jce.provider.")) { + profileCheckProviderNames.add(name); + } else { + profileCheckPropertyNames.add(name); + } + } + } + } + + private void checkProfileCheck(String profileID) { + if (!profileCheckProviderNames.isEmpty()) { + printStackTraceAndExit( + "The order numbers of providers in profile " + profileID + + " (or its base profile) are not consecutive."); + } + if (!profileCheckPropertyNames.isEmpty()) { + printStackTraceAndExit( + "The property names: " + + profileCheckPropertyNames + .stream() + .sorted() + .collect(Collectors.joining(", ")) + + " in profile " + profileID + + " (or its base profile)" + + " are not recognized."); + } + } } /**