From 734336d683e4c66db38c40150a25fb2981131af8 Mon Sep 17 00:00:00 2001 From: Josh Cummings Date: Wed, 6 Nov 2024 13:25:28 -0700 Subject: [PATCH] Polish toLower/UpperCase Usage Apply the common security hardening technique of specifying Locale when calling toUpperCase and toLowerCase Closes gh-963 --- .../ldap/core/LdapRdnComponent.java | 13 +++++++------ .../ldap/core/NameAwareAttributes.java | 9 +++++---- .../ldap/odm/core/impl/CaseIgnoreString.java | 4 +++- .../ldap/support/LdapEncoder.java | 3 ++- etc/checkstyle/checkstyle.xml | 16 ++++++++++++++++ .../ldap/odm/tools/SchemaReader.java | 5 +++-- .../ldap/odm/tools/SchemaToJava.java | 3 ++- .../ad/IncrementalAttributeMapperITests.java | 4 +++- 8 files changed, 41 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/org/springframework/ldap/core/LdapRdnComponent.java b/core/src/main/java/org/springframework/ldap/core/LdapRdnComponent.java index 3d2f65f28..071e4b98e 100644 --- a/core/src/main/java/org/springframework/ldap/core/LdapRdnComponent.java +++ b/core/src/main/java/org/springframework/ldap/core/LdapRdnComponent.java @@ -19,6 +19,7 @@ import java.io.Serializable; import java.net.URI; import java.net.URISyntaxException; +import java.util.Locale; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -75,10 +76,10 @@ public LdapRdnComponent(String key, String value, boolean decodeValue) { String caseFold = System.getProperty(DistinguishedName.KEY_CASE_FOLD_PROPERTY); if (!StringUtils.hasText(caseFold) || caseFold.equals(DistinguishedName.KEY_CASE_FOLD_LOWER)) { - this.key = key.toLowerCase(); + this.key = key.toLowerCase(Locale.ROOT); } else if (caseFold.equals(DistinguishedName.KEY_CASE_FOLD_UPPER)) { - this.key = key.toUpperCase(); + this.key = key.toUpperCase(Locale.ROOT); } else if (caseFold.equals(DistinguishedName.KEY_CASE_FOLD_NONE)) { this.key = key; @@ -88,7 +89,7 @@ else if (caseFold.equals(DistinguishedName.KEY_CASE_FOLD_NONE)) { + "; expected \"" + DistinguishedName.KEY_CASE_FOLD_LOWER + "\", \"" + DistinguishedName.KEY_CASE_FOLD_UPPER + "\", or \"" + DistinguishedName.KEY_CASE_FOLD_NONE + "\""); - this.key = key.toLowerCase(); + this.key = key.toLowerCase(Locale.ROOT); } if (decodeValue) { this.value = LdapEncoder.nameDecode(value); @@ -203,7 +204,7 @@ public boolean equals(Object obj) { */ @Override public int hashCode() { - return this.key.toUpperCase().hashCode() ^ this.value.toUpperCase().hashCode(); + return this.key.toUpperCase(Locale.ROOT).hashCode() ^ this.value.toUpperCase(Locale.ROOT).hashCode(); } /* @@ -228,9 +229,9 @@ public int compareTo(Object obj) { // It's safe to compare directly against key and value, // because they are validated not to be null on instance creation. - int keyCompare = this.key.toLowerCase().compareTo(that.key.toLowerCase()); + int keyCompare = this.key.toLowerCase(Locale.ROOT).compareTo(that.key.toLowerCase(Locale.ROOT)); if (keyCompare == 0) { - return this.value.toLowerCase().compareTo(that.value.toLowerCase()); + return this.value.toLowerCase(Locale.ROOT).compareTo(that.value.toLowerCase(Locale.ROOT)); } else { return keyCompare; diff --git a/core/src/main/java/org/springframework/ldap/core/NameAwareAttributes.java b/core/src/main/java/org/springframework/ldap/core/NameAwareAttributes.java index 2fa088ec0..dd35bd8de 100644 --- a/core/src/main/java/org/springframework/ldap/core/NameAwareAttributes.java +++ b/core/src/main/java/org/springframework/ldap/core/NameAwareAttributes.java @@ -17,6 +17,7 @@ package org.springframework.ldap.core; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import javax.naming.NamingEnumeration; @@ -67,7 +68,7 @@ public int size() { @Override public NameAwareAttribute get(String attrID) { Assert.hasLength(attrID, "Attribute ID must not be empty"); - return this.attributes.get(attrID.toLowerCase()); + return this.attributes.get(attrID.toLowerCase(Locale.ROOT)); } @Override @@ -84,7 +85,7 @@ public NamingEnumeration getIDs() { public Attribute put(String attrID, Object val) { Assert.hasLength(attrID, "Attribute ID must not be empty"); NameAwareAttribute newAttribute = new NameAwareAttribute(attrID, val); - this.attributes.put(attrID.toLowerCase(), newAttribute); + this.attributes.put(attrID.toLowerCase(Locale.ROOT), newAttribute); return newAttribute; } @@ -93,7 +94,7 @@ public Attribute put(String attrID, Object val) { public Attribute put(Attribute attr) { Assert.notNull(attr, "Attribute must not be null"); NameAwareAttribute newAttribute = new NameAwareAttribute(attr); - this.attributes.put(attr.getID().toLowerCase(), newAttribute); + this.attributes.put(attr.getID().toLowerCase(Locale.ROOT), newAttribute); return newAttribute; } @@ -101,7 +102,7 @@ public Attribute put(Attribute attr) { @Override public Attribute remove(String attrID) { Assert.hasLength(attrID, "Attribute ID must not be empty"); - return this.attributes.remove(attrID.toLowerCase()); + return this.attributes.remove(attrID.toLowerCase(Locale.ROOT)); } @Override diff --git a/core/src/main/java/org/springframework/ldap/odm/core/impl/CaseIgnoreString.java b/core/src/main/java/org/springframework/ldap/odm/core/impl/CaseIgnoreString.java index c3586a60a..2f92fcebe 100755 --- a/core/src/main/java/org/springframework/ldap/odm/core/impl/CaseIgnoreString.java +++ b/core/src/main/java/org/springframework/ldap/odm/core/impl/CaseIgnoreString.java @@ -16,6 +16,8 @@ package org.springframework.ldap.odm.core.impl; +import java.util.Locale; + import org.springframework.util.Assert; // A case independent String wrapper. @@ -28,7 +30,7 @@ CaseIgnoreString(String string) { Assert.notNull(string, "string must not be null"); this.string = string; - this.hashCode = string.toUpperCase().hashCode(); + this.hashCode = string.toUpperCase(Locale.ROOT).hashCode(); } @Override diff --git a/core/src/main/java/org/springframework/ldap/support/LdapEncoder.java b/core/src/main/java/org/springframework/ldap/support/LdapEncoder.java index 9cabc6d99..e7ae6339d 100644 --- a/core/src/main/java/org/springframework/ldap/support/LdapEncoder.java +++ b/core/src/main/java/org/springframework/ldap/support/LdapEncoder.java @@ -17,6 +17,7 @@ package org.springframework.ldap.support; import java.util.Base64; +import java.util.Locale; import org.springframework.ldap.BadLdapGrammarException; import org.springframework.util.Assert; @@ -81,7 +82,7 @@ private LdapEncoder() { protected static String toTwoCharHex(char c) { - String raw = Integer.toHexString(c).toUpperCase(); + String raw = Integer.toHexString(c).toUpperCase(Locale.ROOT); if (raw.length() > 1) { return raw; diff --git a/etc/checkstyle/checkstyle.xml b/etc/checkstyle/checkstyle.xml index 1b825ecae..a9903ae8f 100644 --- a/etc/checkstyle/checkstyle.xml +++ b/etc/checkstyle/checkstyle.xml @@ -26,5 +26,21 @@ + + + + + + + + + + + + + + diff --git a/odm/src/main/java/org/springframework/ldap/odm/tools/SchemaReader.java b/odm/src/main/java/org/springframework/ldap/odm/tools/SchemaReader.java index 2a5268912..98ebb9967 100755 --- a/odm/src/main/java/org/springframework/ldap/odm/tools/SchemaReader.java +++ b/odm/src/main/java/org/springframework/ldap/odm/tools/SchemaReader.java @@ -17,6 +17,7 @@ package org.springframework.ldap.odm.tools; import java.util.HashSet; +import java.util.Locale; import java.util.Set; import javax.naming.NamingEnumeration; @@ -156,7 +157,7 @@ private void createObjectClass(Set objectClasses, DirContext schemaConte Attribute currentAttribute = valuesEnumeration.nextElement(); // Get the attribute name and lower case it (as this is all case indep) - String currentId = currentAttribute.getID().toUpperCase(); + String currentId = currentAttribute.getID().toUpperCase(Locale.ROOT); // Is this a MUST, MAY or SUP attribute SchemaAttributeType type = getSchemaAttributeType(currentId); @@ -168,7 +169,7 @@ private void createObjectClass(Set objectClasses, DirContext schemaConte switch (type) { case SUP: // Its a super class - String lowerCased = currentValue.toLowerCase(); + String lowerCased = currentValue.toLowerCase(Locale.ROOT); if (!schema.getObjectClass().contains(lowerCased)) { supList.add(lowerCased); } diff --git a/odm/src/main/java/org/springframework/ldap/odm/tools/SchemaToJava.java b/odm/src/main/java/org/springframework/ldap/odm/tools/SchemaToJava.java index cb6c74c87..2a41a62c5 100755 --- a/odm/src/main/java/org/springframework/ldap/odm/tools/SchemaToJava.java +++ b/odm/src/main/java/org/springframework/ldap/odm/tools/SchemaToJava.java @@ -27,6 +27,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; @@ -340,7 +341,7 @@ private static Set parseObjectClassesFlag(String objectClassesFlag) { for (String objectClassFlag : objectClassesFlag.split(",")) { if (objectClassFlag.length() > 0) { - objectClasses.add(objectClassFlag.toLowerCase().trim()); + objectClasses.add(objectClassFlag.toLowerCase(Locale.ROOT).trim()); } } diff --git a/test/integration-tests-ad/src/test/java/org/springframework/ldap/itest/ad/IncrementalAttributeMapperITests.java b/test/integration-tests-ad/src/test/java/org/springframework/ldap/itest/ad/IncrementalAttributeMapperITests.java index ac705bb90..3132e09b2 100644 --- a/test/integration-tests-ad/src/test/java/org/springframework/ldap/itest/ad/IncrementalAttributeMapperITests.java +++ b/test/integration-tests-ad/src/test/java/org/springframework/ldap/itest/ad/IncrementalAttributeMapperITests.java @@ -18,6 +18,7 @@ import java.io.UnsupportedEncodingException; import java.util.List; +import java.util.Locale; import javax.naming.directory.BasicAttribute; import javax.naming.directory.DirContext; @@ -112,7 +113,8 @@ private void createUser(String username) throws UnsupportedEncodingException { ctx.setAttributeValue("userPrincipalName", username + "@example.com"); ctx.setAttributeValue("cn", username); ctx.setAttributeValue("description", "Dummy user"); - ctx.setAttributeValue("sAMAccountName", username.toUpperCase() + "." + username.toUpperCase()); + ctx.setAttributeValue("sAMAccountName", + username.toUpperCase(Locale.ENGLISH) + "." + username.toUpperCase(Locale.ENGLISH)); ctx.setAttributeValue("userAccountControl", "512"); String newQuotedPassword = "\"" + DEFAULT_PASSWORD + "\"";