Skip to content

Commit

Permalink
Support provider fully-qualified class name in Restricted Security mode
Browse files Browse the repository at this point in the history
Signed-off-by: Tao Liu <tao.liu@ibm.com>
  • Loading branch information
taoliult committed Jun 25, 2024
1 parent 94ee140 commit e32675f
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivilegedAction;
import java.security.Provider;
import java.security.Provider.Service;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
Expand Down Expand Up @@ -267,6 +268,12 @@ public static boolean isServiceAllowed(Service service) {
*/
public static boolean isProviderAllowed(String providerName) {
if (securityEnabled) {
// Remove argument, e.g. -NSS-FIPS, if present.
int pos = providerName.indexOf('-');
if (pos >= 0) {
providerName = providerName.substring(0, pos);
}

return restricts.isRestrictedProviderAllowed(providerName);
}
return true;
Expand All @@ -280,17 +287,17 @@ public static boolean isProviderAllowed(String providerName) {
*/
public static boolean isProviderAllowed(Class<?> providerClazz) {
if (securityEnabled) {
String providerName = providerClazz.getName();
String providerClassName = providerClazz.getName();

// Check if the specified class extends java.security.Provider.
if (java.security.Provider.class.isAssignableFrom(providerClazz)) {
return restricts.isRestrictedProviderAllowed(providerName);
return restricts.isRestrictedProviderAllowed(providerClassName);
}

// For a class that doesn't extend java.security.Provider, no need to
// check allowed or not allowed, always return true to load it.
if (debug != null) {
debug.println("The provider class " + providerName + " does not extend java.security.Provider.");
debug.println("The provider class " + providerClassName + " does not extend java.security.Provider.");
}
}
return true;
Expand Down Expand Up @@ -661,27 +668,6 @@ private static boolean isAsterisk(String string) {
return "*".equals(string);
}

/**
* Get the provider name defined in provider construction method.
*
* @param providerName provider name or provider with packages
* @return provider name defined in provider construction method
*/
private static String getProvidersSimpleName(String providerName) {
if (providerName.equals("com.sun.security.sasl.Provider")) {
// The main class for the SunSASL provider is com.sun.security.sasl.Provider.
return "SunSASL";
} else {
// Remove the provider's class package names if present.
int pos = providerName.lastIndexOf('.');
if (pos >= 0) {
providerName = providerName.substring(pos + 1);
}
// Provider without package names.
return providerName;
}
}

/**
* This class is used to save and operate on restricted security
* properties which are loaded from the java.security file.
Expand Down Expand Up @@ -715,7 +701,7 @@ private static final class RestrictedSecurityProperties {
// Provider with argument (provider name + optional argument).
private final List<String> providers;
// Provider without argument.
private final List<String> providersSimpleName;
private final List<String> providersFullyQualifiedClassName;
// The map is keyed by provider name.
private final Map<String, Constraint[]> providerConstraints;

Expand Down Expand Up @@ -747,7 +733,7 @@ private RestrictedSecurityProperties(String profileID, ProfileParser parser) {
this.jdkFipsMode = parser.getProperty("jdkFipsMode");

this.providers = new ArrayList<>(parser.providers);
this.providersSimpleName = new ArrayList<>(parser.providersSimpleName);
this.providersFullyQualifiedClassName = new ArrayList<>(parser.providersFullyQualifiedClassName);
this.providerConstraints = parser.providerConstraints
.entrySet()
.stream()
Expand All @@ -769,30 +755,26 @@ private RestrictedSecurityProperties(String profileID, ProfileParser parser) {
* @return true if the Service is allowed
*/
boolean isRestrictedServiceAllowed(Service service) {
String providerName = service.getProvider().getName();
Provider provider = service.getProvider();
String providerClassName = provider.getClass().getName();

if (debug != null) {
debug.println("Checking service " + service.toString() + " offered by provider " + providerName + ".");
debug.println("Checking service " + service.toString() + " offered by provider " + providerClassName + ".");
}

// Provider with argument, remove argument.
// e.g. SunPKCS11-NSS-FIPS, remove argument -NSS-FIPS.
int pos = providerName.indexOf('-');
providerName = (pos < 0) ? providerName : providerName.substring(0, pos);

Constraint[] constraints = providerConstraints.get(providerName);
Constraint[] constraints = providerConstraints.get(providerClassName);

if (constraints == null) {
// Disallow unknown providers.
if (debug != null) {
debug.println("Security constraints check."
+ " Disallow unknown provider: " + providerName);
+ " Disallow unknown provider: " + providerClassName);
}
return false;
} else if (constraints.length == 0) {
// Allow this provider with no constraints.
if (debug != null) {
debug.println("No constraints for provider " + providerName + ".");
debug.println("No constraints for provider " + providerClassName + ".");
}
return true;
}
Expand Down Expand Up @@ -836,7 +818,7 @@ boolean isRestrictedServiceAllowed(Service service) {
debug.println("The following service:"
+ "\n\tService type: " + type
+ "\n\tAlgorithm: " + algorithm
+ "\nis allowed in provider: " + providerName);
+ "\nis allowed in provider: " + providerClassName);
}
return true;
}
Expand Down Expand Up @@ -866,7 +848,7 @@ boolean isRestrictedServiceAllowed(Service service) {
+ "\n\tService type: " + type
+ "\n\tAlgorithm: " + algorithm
+ "\n\tAttribute: " + cAttribute
+ "\nis NOT allowed in provider: " + providerName);
+ "\nis NOT allowed in provider: " + providerClassName);
}
return false;
}
Expand All @@ -880,7 +862,7 @@ boolean isRestrictedServiceAllowed(Service service) {
+ "\n\tService type: " + type
+ "\n\tAlgorithm: " + algorithm
+ "\n\tAttribute: " + cAttribute
+ "\nis allowed in provider: " + providerName);
+ "\nis allowed in provider: " + providerClassName);
}
return true;
}
Expand All @@ -891,42 +873,33 @@ boolean isRestrictedServiceAllowed(Service service) {
debug.println("The following service:"
+ "\n\tService type: " + type
+ "\n\tAlgorithm: " + algorithm
+ "\nis NOT allowed in provider: " + providerName);
+ "\nis NOT allowed in provider: " + providerClassName);
}
return false;
}

/**
* Check if the provider is allowed in restricted security mode.
*
* @param providerName the provider to check
* @param providerClassName the provider to check
* @return true if the provider is allowed
*/
boolean isRestrictedProviderAllowed(String providerName) {
boolean isRestrictedProviderAllowed(String providerClassName) {
if (debug != null) {
debug.println("Checking the provider " + providerName + " in restricted security mode.");
}

// Remove argument, e.g. -NSS-FIPS, if present.
int pos = providerName.indexOf('-');
if (pos >= 0) {
providerName = providerName.substring(0, pos);
debug.println("Checking the provider " + providerClassName + " in restricted security mode.");
}

// Provider name defined in provider construction method.
providerName = getProvidersSimpleName(providerName);

// Check if the provider is in restricted security provider list.
// If not, the provider won't be registered.
if (providersSimpleName.contains(providerName)) {
// Check if the provider fully-qualified cLass name is in restricted
// security provider list. If not, the provider won't be registered.
if (providersFullyQualifiedClassName.contains(providerClassName)) {
if (debug != null) {
debug.println("The provider " + providerName + " is allowed in restricted security mode.");
debug.println("The provider " + providerClassName + " is allowed in restricted security mode.");
}
return true;
}

if (debug != null) {
debug.println("The provider " + providerName + " is not allowed in restricted security mode.");
debug.println("The provider " + providerClassName + " is not allowed in restricted security mode.");

debug.println("Stack trace:");
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
Expand Down Expand Up @@ -965,8 +938,8 @@ private void listUsedProfile() {
for (int providerPosition = 0; providerPosition < providers.size(); providerPosition++) {
printProperty(profileID + ".jce.provider." + (providerPosition + 1) + ": ",
providers.get(providerPosition));
String providerSimpleName = providersSimpleName.get(providerPosition);
for (Constraint providerConstraint : providerConstraints.get(providerSimpleName)) {
String providerFullyQualifiedClassName = providersFullyQualifiedClassName.get(providerPosition);
for (Constraint providerConstraint : providerConstraints.get(providerFullyQualifiedClassName)) {
System.out.println("\t" + providerConstraint.toString());
}
}
Expand Down Expand Up @@ -1009,7 +982,7 @@ private static final class ProfileParser {
// Provider with argument (provider name + optional argument).
private final List<String> providers;
// Provider without argument.
private final List<String> providersSimpleName;
private final List<String> providersFullyQualifiedClassName;
// The map is keyed by provider name.
private final Map<String, List<Constraint>> providerConstraints;

Expand Down Expand Up @@ -1037,7 +1010,7 @@ private ProfileParser(String id, Properties props) {
profileProperties = new HashMap<>();

providers = new ArrayList<>();
providersSimpleName = new ArrayList<>();
providersFullyQualifiedClassName = new ArrayList<>();
providerConstraints = new HashMap<>();

profilesHashes = new HashMap<>();
Expand Down Expand Up @@ -1198,21 +1171,13 @@ private void parseProvider(String providerInfo, int providerPos, boolean update)
}
providerName = providerName.trim();

// Remove argument, e.g. -NSS-FIPS, if present.
pos = providerName.indexOf('-');
if (pos >= 0) {
providerName = providerName.substring(0, pos);
}

// Provider name defined in provider construction method.
providerName = getProvidersSimpleName(providerName);
boolean providerChanged = false;
if (update) {
String previousProviderName = providersSimpleName.get(providerPos - 1);
String previousProviderName = providersFullyQualifiedClassName.get(providerPos - 1);
providerChanged = !previousProviderName.equals(providerName);
providersSimpleName.set(providerPos - 1, providerName);
providersFullyQualifiedClassName.set(providerPos - 1, providerName);
} else {
providersSimpleName.add(providerPos - 1, providerName);
providersFullyQualifiedClassName.add(providerPos - 1, providerName);
}

if (debug != null) {
Expand All @@ -1228,14 +1193,14 @@ private void removeProvider(String profileExtensionId, int providerPos) {
debug.println("\t\tRemoving provider in position " + providerPos);
}

int numOfExistingProviders = providersSimpleName.size();
int numOfExistingProviders = providersFullyQualifiedClassName.size();

// If this is the last provider, remove from all lists.
if (providerPos == numOfExistingProviders) {
if (debug != null) {
debug.println("\t\t\tLast provider. Only one to be removed.");
}
String providerRemoved = providersSimpleName.remove(providerPos - 1);
String providerRemoved = providersFullyQualifiedClassName.remove(providerPos - 1);
providers.remove(providerPos - 1);
providerConstraints.remove(providerRemoved);

Expand All @@ -1259,7 +1224,7 @@ private void removeProvider(String profileExtensionId, int providerPos) {
}

// Remove all of the providers that are set to empty.
String providerRemoved = providersSimpleName.remove(i - 1);
String providerRemoved = providersFullyQualifiedClassName.remove(i - 1);
providers.remove(i - 1);
providerConstraints.remove(providerRemoved);

Expand Down Expand Up @@ -1308,7 +1273,7 @@ private void initProviders(String profileID, List<String> allInfo) {

private void updateProviders(String profileExtensionId, List<String> allInfo) {
boolean removedProvider = false;
int numOfExistingProviders = providersSimpleName.size();
int numOfExistingProviders = providersFullyQualifiedClassName.size();
// Deal with update of existing providers.
for (int i = 1; i <= numOfExistingProviders; i++) {
String property = profileExtensionId + ".jce.provider." + i;
Expand Down
21 changes: 14 additions & 7 deletions src/java.base/share/classes/sun/security/jca/ProviderConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

/*
* ===========================================================================
* (c) Copyright IBM Corp. 2022, 2023 All Rights Reserved
* (c) Copyright IBM Corp. 2023, 2024 All Rights Reserved
* ===========================================================================
*/

Expand Down Expand Up @@ -170,19 +170,22 @@ public String toString() {
// com.sun.net.ssl.internal.ssl.Provider has been deprecated since JDK 9
@SuppressWarnings("deprecation")
synchronized Provider getProvider() {
if (!RestrictedSecurity.isProviderAllowed(provName)) {
// We're in restricted security mode which does not allow this provider,
// return without loading.
return null;
}
// volatile variable load
Provider p = provider;
// There is RestrictedSecurity check in the ServiceLoader before the
// provider is initialized. So the check has already occurred for the
// provider where provider != null.
if (p != null) {
return p;
}
if (shouldLoad() == false) {
return null;
}
if (!RestrictedSecurity.isProviderAllowed(provName)) {
// We're in restricted security mode which does not allow this provider,
// return without loading.
return null;
}

// Create providers which are in java.base directly
if (provName.equals("SUN") || provName.equals("sun.security.provider.Sun")) {
Expand Down Expand Up @@ -361,8 +364,12 @@ public Provider load(String pn) {
if (debug != null) {
debug.println("Found SL Provider named " + pName);
}
if (pName.equals(pn)) {
if (p.getClass().getName().equals(pn)) {
return p;
} else if (pName.equals(pn)) {
if (!RestrictedSecurity.isEnabled()) {
return p;
}
}
} catch (SecurityException | ServiceConfigurationError |
InvalidParameterException ex) {
Expand Down
13 changes: 6 additions & 7 deletions src/java.base/share/classes/sun/security/jca/ProviderList.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

/*
* ===========================================================================
* (c) Copyright IBM Corp. 2023, 2023 All Rights Reserved
* (c) Copyright IBM Corp. 2023, 2024 All Rights Reserved
* ===========================================================================
*/

Expand Down Expand Up @@ -114,15 +114,14 @@ public static ProviderList add(ProviderList providerList, Provider p) {

public static ProviderList insertAt(ProviderList providerList, Provider p,
int position) {
String providerName = p.getName();
if (providerList.getProvider(providerName) != null) {
return providerList;
}
if (!RestrictedSecurity.isProviderAllowed(providerName)) {
if (!RestrictedSecurity.isProviderAllowed(p.getClass())) {
// We're in restricted security mode which does not allow this provider,
// return without adding.
return providerList;
}
if (providerList.getProvider(p.getName()) != null) {
return providerList;
}
List<ProviderConfig> list = new ArrayList<>
(Arrays.asList(providerList.configs));
int n = list.size();
Expand Down Expand Up @@ -155,7 +154,7 @@ public static ProviderList newList(Provider ... providers) {
if (RestrictedSecurity.isEnabled()) {
List<Provider> allowedProviders = new ArrayList<>();
for (Provider p : providers) {
if (RestrictedSecurity.isProviderAllowed(p.getName())) {
if (RestrictedSecurity.isProviderAllowed(p.getClass())) {
// This provider is allowed, add it the list.
allowedProviders.add(p);
}
Expand Down
Loading

0 comments on commit e32675f

Please sign in to comment.