浏览代码

Merge branch 'master' into enh-domainadmin

Jason Rivard 3 年之前
父节点
当前提交
7770a3aa79
共有 100 个文件被更改,包括 380 次插入694 次删除
  1. 6 0
      CHANGES.md
  2. 1 1
      client/pom.xml
  3. 2 2
      data-service/pom.xml
  4. 1 1
      lib-data/pom.xml
  5. 1 1
      lib-util/pom.xml
  6. 9 1
      lib-util/src/main/java/password/pwm/util/java/CollectionUtil.java
  7. 2 8
      lib-util/src/main/java/password/pwm/util/java/ConditionalTaskExecutor.java
  8. 5 0
      lib-util/src/main/java/password/pwm/util/java/StringUtil.java
  9. 0 5
      lib-util/src/main/java/password/pwm/util/java/TimeDuration.java
  10. 11 5
      pom.xml
  11. 3 3
      server/pom.xml
  12. 1 1
      server/src/main/java/password/pwm/PwmApplication.java
  13. 5 5
      server/src/main/java/password/pwm/PwmEnvironment.java
  14. 2 2
      server/src/main/java/password/pwm/config/LDAPPermissionInfo.java
  15. 3 2
      server/src/main/java/password/pwm/config/PwmSetting.java
  16. 1 1
      server/src/main/java/password/pwm/config/PwmSettingMetaDataReader.java
  17. 1 1
      server/src/main/java/password/pwm/config/PwmSettingXml.java
  18. 1 1
      server/src/main/java/password/pwm/config/StoredSettingReader.java
  19. 14 0
      server/src/main/java/password/pwm/config/profile/AbstractProfile.java
  20. 1 1
      server/src/main/java/password/pwm/config/profile/PwmPasswordRule.java
  21. 2 2
      server/src/main/java/password/pwm/config/stored/ConfigurationCleaner.java
  22. 3 1
      server/src/main/java/password/pwm/config/stored/ConfigurationReader.java
  23. 86 0
      server/src/main/java/password/pwm/config/stored/ConfigurationVerifier.java
  24. 0 1
      server/src/main/java/password/pwm/config/stored/StoredConfigZipJsonSerializer.java
  25. 2 2
      server/src/main/java/password/pwm/config/stored/StoredConfigurationUtil.java
  26. 0 1
      server/src/main/java/password/pwm/config/value/AbstractValue.java
  27. 0 2
      server/src/main/java/password/pwm/config/value/CustomLinkValue.java
  28. 0 2
      server/src/main/java/password/pwm/config/value/OptionListValue.java
  29. 2 2
      server/src/main/java/password/pwm/config/value/StoredValueEncoder.java
  30. 0 2
      server/src/main/java/password/pwm/config/value/UserPermissionValue.java
  31. 2 2
      server/src/main/java/password/pwm/config/value/ValueTypeConverter.java
  32. 0 2
      server/src/main/java/password/pwm/config/value/VerificationMethodValue.java
  33. 2 2
      server/src/main/java/password/pwm/health/ApplianceStatusChecker.java
  34. 1 1
      server/src/main/java/password/pwm/health/HealthMessage.java
  35. 1 1
      server/src/main/java/password/pwm/health/HealthStatus.java
  36. 1 1
      server/src/main/java/password/pwm/health/HealthTopic.java
  37. 1 1
      server/src/main/java/password/pwm/health/LDAPHealthChecker.java
  38. 2 2
      server/src/main/java/password/pwm/http/ContextManager.java
  39. 1 1
      server/src/main/java/password/pwm/http/JspUtility.java
  40. 2 2
      server/src/main/java/password/pwm/http/PwmResponse.java
  41. 2 2
      server/src/main/java/password/pwm/http/SessionManager.java
  42. 41 71
      server/src/main/java/password/pwm/http/auth/CASFilterAuthenticationProvider.java
  43. 1 1
      server/src/main/java/password/pwm/http/bean/SetupOtpBean.java
  44. 1 1
      server/src/main/java/password/pwm/http/filter/ApplicationModeFilter.java
  45. 0 42
      server/src/main/java/password/pwm/http/filter/RequestInitializationFilter.java
  46. 2 2
      server/src/main/java/password/pwm/http/servlet/GuestRegistrationServlet.java
  47. 1 1
      server/src/main/java/password/pwm/http/servlet/LogoutServlet.java
  48. 1 1
      server/src/main/java/password/pwm/http/servlet/configeditor/ConfigEditorServlet.java
  49. 1 1
      server/src/main/java/password/pwm/http/servlet/configguide/ConfigGuideServlet.java
  50. 2 2
      server/src/main/java/password/pwm/http/servlet/configguide/ConfigGuideUtils.java
  51. 1 1
      server/src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskServlet.java
  52. 1 1
      server/src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskServletUtil.java
  53. 2 2
      server/src/main/java/password/pwm/http/servlet/oauth/OAuthConsumerServlet.java
  54. 1 1
      server/src/main/java/password/pwm/http/servlet/peoplesearch/PhotoDataReader.java
  55. 4 4
      server/src/main/java/password/pwm/http/servlet/updateprofile/UpdateProfileServlet.java
  56. 1 1
      server/src/main/java/password/pwm/http/tag/conditional/PwmIfTag.java
  57. 1 1
      server/src/main/java/password/pwm/http/tag/url/PwmThemeURL.java
  58. 1 1
      server/src/main/java/password/pwm/http/tag/value/PwmValueTag.java
  59. 49 26
      server/src/main/java/password/pwm/ldap/LdapOperationsHelper.java
  60. 2 2
      server/src/main/java/password/pwm/ldap/UserInfoReader.java
  61. 1 1
      server/src/main/java/password/pwm/svc/PwmServiceManager.java
  62. 2 2
      server/src/main/java/password/pwm/svc/cr/CrService.java
  63. 5 5
      server/src/main/java/password/pwm/svc/cr/NMASCrOperator.java
  64. 2 2
      server/src/main/java/password/pwm/svc/db/DatabaseAccessorImpl.java
  65. 5 5
      server/src/main/java/password/pwm/svc/db/DatabaseUtil.java
  66. 1 1
      server/src/main/java/password/pwm/svc/intruder/IntruderDomainService.java
  67. 5 5
      server/src/main/java/password/pwm/svc/intruder/StubRecordManager.java
  68. 1 1
      server/src/main/java/password/pwm/svc/otp/AbstractOtpOperator.java
  69. 3 5
      server/src/main/java/password/pwm/svc/otp/DbOtpOperator.java
  70. 2 4
      server/src/main/java/password/pwm/svc/otp/LdapOtpOperator.java
  71. 3 5
      server/src/main/java/password/pwm/svc/otp/LocalDbOtpOperator.java
  72. 2 2
      server/src/main/java/password/pwm/svc/otp/OtpService.java
  73. 1 8
      server/src/main/java/password/pwm/svc/otp/PasscodeGenerator.java
  74. 1 1
      server/src/main/java/password/pwm/svc/secure/AbstractSecureService.java
  75. 2 2
      server/src/main/java/password/pwm/svc/sms/SmsQueueService.java
  76. 13 17
      server/src/main/java/password/pwm/svc/wordlist/SharedHistoryService.java
  77. 0 352
      server/src/main/java/password/pwm/util/IPMatcher.java
  78. 1 1
      server/src/main/java/password/pwm/util/cli/MainClass.java
  79. 1 1
      server/src/main/java/password/pwm/util/debug/AboutItemGenerator.java
  80. 1 1
      server/src/main/java/password/pwm/util/debug/DebugItemGenerator.java
  81. 1 1
      server/src/main/java/password/pwm/util/form/FormUtility.java
  82. 1 1
      server/src/main/java/password/pwm/util/i18n/LocaleHelper.java
  83. 4 4
      server/src/main/java/password/pwm/util/i18n/LocaleStats.java
  84. 5 5
      server/src/main/java/password/pwm/util/localdb/AbstractJDBCLocalDB.java
  85. 1 1
      server/src/main/java/password/pwm/util/localdb/LocalDBUtility.java
  86. 1 1
      server/src/main/java/password/pwm/util/logging/PwmLogger.java
  87. 3 3
      server/src/main/java/password/pwm/util/macro/StaticMacros.java
  88. 4 7
      server/src/main/java/password/pwm/util/operations/ActionExecutor.java
  89. 2 2
      server/src/main/java/password/pwm/util/password/PasswordRuleChecks.java
  90. 1 1
      server/src/main/java/password/pwm/util/password/PasswordRuleReaderHelper.java
  91. 1 1
      server/src/main/java/password/pwm/util/password/PasswordUtility.java
  92. 3 3
      server/src/main/java/password/pwm/util/password/PwmPasswordRuleValidator.java
  93. 1 1
      server/src/main/java/password/pwm/util/secure/PwmTrustManager.java
  94. 1 1
      server/src/main/java/password/pwm/util/secure/SecureEngine.java
  95. 1 1
      server/src/main/java/password/pwm/ws/server/rest/RestCheckPasswordServer.java
  96. 1 1
      server/src/main/resources/password/pwm/config/PwmSetting.xml
  97. 1 1
      server/src/main/resources/password/pwm/i18n/PwmSetting.properties
  98. 1 1
      webapp/src/main/webapp/WEB-INF/jsp/forgottenpassword-method.jsp
  99. 1 1
      webapp/src/main/webapp/WEB-INF/jsp/fragment/ldap-permissions.jsp
  100. 1 1
      webapp/src/main/webapp/WEB-INF/jsp/fragment/setupresponses-form.jsp

+ 6 - 0
CHANGES.md

@@ -1,5 +1,11 @@
 # Changelog
 
+## [2.1.0] - Not yet released
+### New
+- Multi-Domain support (aka multi-tenant), each domain can server a specific host url with independent configuration and management 
+### Changed
+- Removed setting 'Security ⇨ Web Security ⇨ Permitted IP Network Addresses', this functionality is better provided by the web server itself.
+
 ## [2.0.1] - Released March 11, 2022
 ### Changed
 - Issue #573 - PWM 5081 at the end of user activation ( no profile assigned )

+ 1 - 1
client/pom.xml

@@ -53,7 +53,7 @@
             </plugin>
             <plugin>
                 <artifactId>maven-clean-plugin</artifactId>
-                <version>3.1.0</version>
+                <version>3.2.0</version>
                 <executions>
                     <execution>
                         <id>remove-client-files</id>

+ 2 - 2
data-service/pom.xml

@@ -93,7 +93,7 @@
             </plugin>
             <plugin>
                 <artifactId>maven-clean-plugin</artifactId>
-                <version>3.1.0</version>
+                <version>3.2.0</version>
             </plugin>
 
             <plugin>
@@ -227,7 +227,7 @@
         <dependency>
             <groupId>org.jetbrains.xodus</groupId>
             <artifactId>xodus-environment</artifactId>
-            <version>1.3.232</version>
+            <version>2.0.1</version>
         </dependency>
     </dependencies>
 </project>

+ 1 - 1
lib-data/pom.xml

@@ -40,7 +40,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
-                <version>3.0.0-M5</version>
+                <version>3.0.0-M6</version>
                 <executions>
                     <execution>
                         <id>default-test</id>

+ 1 - 1
lib-util/pom.xml

@@ -40,7 +40,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
-                <version>3.0.0-M5</version>
+                <version>3.0.0-M6</version>
                 <executions>
                     <execution>
                         <id>default-test</id>

+ 9 - 1
lib-util/src/main/java/password/pwm/util/java/CollectionUtil.java

@@ -20,6 +20,8 @@
 
 package password.pwm.util.java;
 
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -156,7 +158,13 @@ public class CollectionUtil
                 .collect( Collectors.toUnmodifiableList() );
     }
 
-    public static <K, V> Map<K, V> combineMaps( final List<Map<K, V>> maps )
+    /**
+     * Combines an ordered sequence of ordered maps.  Duplicate keys in later maps in the list will
+     * silently overwrite the earlier values.  The returned map will be unmodifiable as per
+     * {@link Collections#unmodifiableMap(Map)}.
+     */
+    @SuppressFBWarnings( "OCP_OVERLY_CONCRETE_PARAMETER" )
+    public static <K, V> Map<K, V> combineOrderedMaps( final List<Map<K, V>> maps )
     {
         final Map<K, V> returnMap = new LinkedHashMap<>();
         for ( final Map<K, V> loopMap : maps )

+ 2 - 8
lib-util/src/main/java/password/pwm/util/java/ConditionalTaskExecutor.java

@@ -53,14 +53,8 @@ public class ConditionalTaskExecutor
         {
             if ( predicate.getAsBoolean() )
             {
-                try
-                {
-                    task.run();
-                }
-                catch ( final Throwable t )
-                {
-                    throw new RuntimeException( t );
-                }
+
+                task.run();
             }
         }
         finally

+ 5 - 0
lib-util/src/main/java/password/pwm/util/java/StringUtil.java

@@ -20,6 +20,7 @@
 
 package password.pwm.util.java;
 
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import org.apache.commons.codec.binary.Base32;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.text.StringEscapeUtils;
@@ -278,6 +279,7 @@ public abstract class StringUtil
         return StringEscapeUtils.escapeXml11( input );
     }
 
+    @SuppressFBWarnings( "EXS_EXCEPTION_SOFTENING_NO_CONSTRAINTS" )
     public static String urlEncode( final String input )
     {
         try
@@ -290,6 +292,7 @@ public abstract class StringUtil
         }
     }
 
+    @SuppressFBWarnings( "EXS_EXCEPTION_SOFTENING_NO_CONSTRAINTS" )
     public static String urlDecode( final String input )
     {
         try
@@ -309,6 +312,7 @@ public abstract class StringUtil
         return new String( base32.encode( input ), STRING_UTIL_CHARSET.toString() );
     }
 
+    @SuppressFBWarnings( "EXS_EXCEPTION_SOFTENING_NO_CONSTRAINTS" )
     public static byte[] base64Decode( final CharSequence input, final StringUtil.Base64Options... options )
             throws IOException
     {
@@ -337,6 +341,7 @@ public abstract class StringUtil
         }
     }
 
+    @SuppressFBWarnings( "EXS_EXCEPTION_SOFTENING_NO_CONSTRAINTS" )
     public static String base64Encode( final byte[] input, final StringUtil.Base64Options... options )
     {
         final byte[] compressedBytes;

+ 0 - 5
lib-util/src/main/java/password/pwm/util/java/TimeDuration.java

@@ -127,11 +127,6 @@ public class TimeDuration implements Comparable<TimeDuration>, Serializable
         return TimeDuration.fromCurrent( instant ).asCompactString();
     }
 
-    public static String asCompactString( final long ms )
-    {
-        return newTimeDuration( ms ).asCompactString();
-    }
-
     public long asMillis()
     {
         return ms;

+ 11 - 5
pom.xml

@@ -148,7 +148,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-javadoc-plugin</artifactId>
-                <version>3.3.2</version>
+                <version>3.4.0</version>
                 <executions>
                     <execution>
                         <goals>
@@ -238,7 +238,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
-                <version>3.10.0</version>
+                <version>3.10.1</version>
                 <configuration>
                     <source>${maven.compiler.source}</source>
                     <target>${maven.compiler.target}</target>
@@ -402,6 +402,7 @@
                         <goals>
                             <goal>check</goal>
                         </goals>
+                        <phase>verify</phase>
                     </execution>
                 </executions>
                 <configuration>
@@ -437,6 +438,11 @@
                     </includes>
                 </configuration>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <version>3.3.0</version>
+            </plugin>
         </plugins>
     </build>
 
@@ -445,7 +451,7 @@
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
-            <version>1.18.22</version>
+            <version>1.18.24</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
@@ -465,7 +471,7 @@
         <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
-            <version>4.4.0</version>
+            <version>4.5.0</version>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -477,7 +483,7 @@
         <dependency>
             <groupId>com.github.tomakehurst</groupId>
             <artifactId>wiremock-jre8</artifactId>
-            <version>2.32.0</version>
+            <version>2.33.1</version>
             <scope>test</scope>
         </dependency>
         <dependency>

+ 3 - 3
server/pom.xml

@@ -41,7 +41,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
-                <version>3.0.0-M5</version>
+                <version>3.0.0-M6</version>
                 <executions>
                     <execution>
                         <id>default-test</id>
@@ -306,7 +306,7 @@
         <dependency>
             <groupId>org.jetbrains.xodus</groupId>
             <artifactId>xodus-environment</artifactId>
-            <version>1.3.232</version>
+            <version>2.0.1</version>
         </dependency>
 
         <dependency>
@@ -327,7 +327,7 @@
         <dependency>
             <groupId>com.nulab-inc</groupId>
             <artifactId>zxcvbn</artifactId>
-            <version>1.5.2</version>
+            <version>1.7.0</version>
         </dependency>
         <dependency>
             <groupId>com.github.ziplet</groupId>

+ 1 - 1
server/src/main/java/password/pwm/PwmApplication.java

@@ -545,7 +545,7 @@ public class PwmApplication
                 else
                 {
                     LOGGER.error( () -> "can not output tomcat configuration file, source file parameter '"
-                            + PwmEnvironment.ApplicationParameter.AutoWriteTomcatConfSourceFile.toString() + "' is not specified." );
+                            + PwmEnvironment.ApplicationParameter.AutoWriteTomcatConfSourceFile + "' is not specified." );
                     return;
                 }
             }

+ 5 - 5
server/src/main/java/password/pwm/PwmEnvironment.java

@@ -110,12 +110,12 @@ public class PwmEnvironment
 
         public String conicalJavaOptionSystemName( )
         {
-            return PwmConstants.PWM_APP_NAME.toLowerCase() + "." + this.toString();
+            return PwmConstants.PWM_APP_NAME.toLowerCase() + "." + this;
         }
 
         public String conicalEnvironmentSystemName( )
         {
-            return ( PwmConstants.PWM_APP_NAME.toLowerCase() + "_" + this.toString() ).toUpperCase();
+            return ( PwmConstants.PWM_APP_NAME.toLowerCase() + "_" + this ).toUpperCase();
         }
 
         public List<String> possibleNames( final String contextName )
@@ -128,7 +128,7 @@ public class PwmEnvironment
                         + "."
                         + contextName
                         + "."
-                        + this.toString();
+                        + this;
                 returnValues.add( value );
                 returnValues.add( value.toUpperCase() );
                 returnValues.add( value.replace( '.', '_' ) );
@@ -138,7 +138,7 @@ public class PwmEnvironment
                 // java property format <app>.<paramName> like pwm.applicationFlag
                 final String value = PwmConstants.PWM_APP_NAME.toLowerCase()
                         + "."
-                        + this.toString();
+                        + this;
                 returnValues.add( value );
                 returnValues.add( value.toUpperCase() );
                 returnValues.add( value.replace( '.', '_' ) );
@@ -310,7 +310,7 @@ public class PwmEnvironment
                 }
                 else
                 {
-                    LOGGER.warn( () -> "unknown " + EnvironmentParameter.applicationFlags.toString() + " value: " + input );
+                    LOGGER.warn( () -> "unknown " + EnvironmentParameter.applicationFlags + " value: " + input );
                 }
             }
             return returnFlags;

+ 2 - 2
server/src/main/java/password/pwm/config/LDAPPermissionInfo.java

@@ -64,13 +64,13 @@ public class LDAPPermissionInfo implements Serializable
 
         public String getLabel( final Locale locale, final DomainConfig config )
         {
-            return LocaleHelper.getLocalizedMessage( locale, "Actor_Label_" + this.toString(), config, Config.class );
+            return LocaleHelper.getLocalizedMessage( locale, "Actor_Label_" + this, config, Config.class );
         }
 
         public String getDescription( final Locale locale, final DomainConfig config )
         {
             final MacroRequest macroRequest = MacroRequest.forStatic();
-            return macroRequest.expandMacros( LocaleHelper.getLocalizedMessage( locale, "Actor_Description_" + this.toString(), config, Config.class ) );
+            return macroRequest.expandMacros( LocaleHelper.getLocalizedMessage( locale, "Actor_Description_" + this, config, Config.class ) );
         }
     }
 }

+ 3 - 2
server/src/main/java/password/pwm/config/PwmSetting.java

@@ -583,8 +583,6 @@ public enum PwmSetting
             "network.allowMultiIPSession", PwmSettingSyntax.BOOLEAN, PwmSettingCategory.WEB_SECURITY ),
     REQUIRED_HEADERS(
             "network.requiredHttpHeaders", PwmSettingSyntax.STRING_ARRAY, PwmSettingCategory.WEB_SECURITY ),
-    IP_PERMITTED_RANGE(
-            "network.ip.permittedRange", PwmSettingSyntax.STRING_ARRAY, PwmSettingCategory.WEB_SECURITY ),
     SECURITY_PAGE_LEAVE_NOTICE_TIMEOUT(
             "security.page.leaveNoticeTimeout", PwmSettingSyntax.NUMERIC, PwmSettingCategory.WEB_SECURITY ),
     SECURITY_PREVENT_FRAMING(
@@ -1268,6 +1266,9 @@ public enum PwmSetting
 
 
     // deprecated.
+    // deprecated 2022-04-20
+    IP_PERMITTED_RANGE(
+            "network.ip.permittedRange", PwmSettingSyntax.STRING_ARRAY, PwmSettingCategory.WEB_SECURITY ),
 
     // deprecated 2019-06-01
     PUBLIC_HEALTH_STATS_WEBSERVICES(

+ 1 - 1
server/src/main/java/password/pwm/config/PwmSettingMetaDataReader.java

@@ -388,7 +388,7 @@ public class PwmSettingMetaDataReader
                     }
                     catch ( final PatternSyntaxException e )
                     {
-                        final String errorMsg = "error compiling regex constraints for setting " + pwmSetting.toString() + ", error: " + e.getMessage();
+                        final String errorMsg = "error compiling regex constraints for setting " + pwmSetting + ", error: " + e.getMessage();
                         LOGGER.error( () -> errorMsg, e );
                         throw new IllegalStateException( errorMsg, e );
                     }

+ 1 - 1
server/src/main/java/password/pwm/config/PwmSettingXml.java

@@ -120,7 +120,7 @@ public class PwmSettingXml
     {
         final String expression = "/settings/template[@key=\"" + template.toString() + "\"]";
         return XML_DOC_CACHE.get().evaluateXpathToElement( expression )
-                .orElseThrow( () -> new IllegalStateException( "PwmSetting.xml is missing template for key '" + template.toString() + "'" ) );
+                .orElseThrow( () -> new IllegalStateException( "PwmSetting.xml is missing template for key '" + template + "'" ) );
     }
 
     static Set<PwmSettingTemplate> parseTemplateAttribute( final XmlElement element )

+ 1 - 1
server/src/main/java/password/pwm/config/StoredSettingReader.java

@@ -198,7 +198,7 @@ public class StoredSettingReader implements SettingReader
 
         if ( PwmSettingSyntax.PRIVATE_KEY != setting.getSyntax() )
         {
-            throw new IllegalArgumentException( "may not read PRIVATE_KEY value for setting: " + setting.toString() );
+            throw new IllegalArgumentException( "may not read PRIVATE_KEY value for setting: " + setting );
         }
 
         return ( PrivateKeyCertificate ) readSetting( setting ).toNativeObject();

+ 14 - 0
server/src/main/java/password/pwm/config/profile/AbstractProfile.java

@@ -30,6 +30,7 @@ import password.pwm.config.value.data.ActionConfiguration;
 import password.pwm.config.value.data.FormConfiguration;
 import password.pwm.config.value.data.UserPermission;
 import password.pwm.util.PasswordData;
+import password.pwm.util.java.JavaHelper;
 
 import java.security.cert.X509Certificate;
 import java.util.Collections;
@@ -45,6 +46,13 @@ public abstract class AbstractProfile implements Profile
     private final StoredConfiguration storedConfiguration;
     private final StoredSettingReader settingReader;
 
+    public enum GuidMode
+    {
+        DN,
+        VENDORGUID,
+        ATTRIBUTE,
+    }
+
     AbstractProfile( final DomainID domainID, final String identifier, final StoredConfiguration storedConfiguration )
     {
         this.identifier = identifier;
@@ -162,4 +170,10 @@ public abstract class AbstractProfile implements Profile
         }
         return Collections.unmodifiableSet( result );
     }
+
+    public GuidMode readGuidMode()
+    {
+        final String guidAttributeName = readSettingAsString( PwmSetting.LDAP_GUID_ATTRIBUTE );
+        return JavaHelper.readEnumFromString( GuidMode.class, guidAttributeName ).orElse( GuidMode.VENDORGUID );
+    }
 }

+ 1 - 1
server/src/main/java/password/pwm/config/profile/PwmPasswordRule.java

@@ -468,7 +468,7 @@ public enum PwmPasswordRule
 
     public String getLabel( final Locale locale, final DomainConfig config )
     {
-        final String key = "Rule_" + this.toString();
+        final String key = "Rule_" + this;
         try
         {
             return LocaleHelper.getLocalizedMessage( locale, key, config, Message.class );

+ 2 - 2
server/src/main/java/password/pwm/config/stored/ConfigurationCleaner.java

@@ -212,7 +212,7 @@ public class ConfigurationCleaner
 
             for ( final String destProfile : targetProfiles )
             {
-                LOGGER.info( () -> "moving setting " + key.toString() + " without profile attribute to profile \"" + destProfile + "\"." );
+                LOGGER.info( () -> "moving setting " + key + " without profile attribute to profile \"" + destProfile + "\"." );
                 {
                     try
                     {
@@ -229,7 +229,7 @@ public class ConfigurationCleaner
 
             try
             {
-                LOGGER.info( () -> "removing setting " + key.toString() + " without profile" );
+                LOGGER.info( () -> "removing setting " + key + " without profile" );
                 modifier.deleteKey( key );
             }
             catch ( final PwmUnrecoverableException e )

+ 3 - 1
server/src/main/java/password/pwm/config/stored/ConfigurationReader.java

@@ -164,6 +164,8 @@ public class ConfigurationReader
                 this.configMode = PwmApplicationMode.ERROR;
                 throw new PwmUnrecoverableException( errorInformation );
             }
+
+            ConfigurationVerifier.verifyConfiguration( storedConfiguration );
         }
         catch ( final Exception e )
         {
@@ -240,7 +242,7 @@ public class ConfigurationReader
             if ( !backupDirectory.mkdirs() )
             {
                 throw new PwmOperationalException( new ErrorInformation( PwmError.ERROR_INTERNAL,
-                        "unable to create backup directory structure '" + backupDirectory.toString() + "'" ) );
+                        "unable to create backup directory structure '" + backupDirectory + "'" ) );
             }
         }
 

+ 86 - 0
server/src/main/java/password/pwm/config/stored/ConfigurationVerifier.java

@@ -0,0 +1,86 @@
+/*
+ * Password Management Servlets (PWM)
+ * http://www.pwm-project.org
+ *
+ * Copyright (c) 2006-2009 Novell, Inc.
+ * Copyright (c) 2009-2021 The PWM Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package password.pwm.config.stored;
+
+import password.pwm.PwmConstants;
+import password.pwm.bean.DomainID;
+import password.pwm.config.PwmSetting;
+import password.pwm.config.value.StoredValue;
+import password.pwm.config.value.ValueTypeConverter;
+import password.pwm.error.PwmError;
+import password.pwm.error.PwmUnrecoverableException;
+import password.pwm.util.java.CollectionUtil;
+
+import java.util.List;
+import java.util.Optional;
+
+class ConfigurationVerifier
+{
+    private static final List<Verifier> VERIFIERS = List.of(
+            new BlockDeprecatedPermittedIpMaskSetting()
+    );
+
+    static void verifyConfiguration(
+            final StoredConfiguration storedConfiguration
+    )
+            throws PwmUnrecoverableException
+    {
+        for ( final Verifier verifier : VERIFIERS )
+        {
+            verifier.verify( storedConfiguration );
+        }
+    }
+
+    interface Verifier
+    {
+        void verify( StoredConfiguration storedConfiguration )
+                throws PwmUnrecoverableException;
+
+    }
+
+    private static class BlockDeprecatedPermittedIpMaskSetting implements Verifier
+    {
+        @Override
+        public void verify( final StoredConfiguration storedConfiguration )
+                throws PwmUnrecoverableException
+        {
+            final StoredConfigKey interestedKey = StoredConfigKey.forSetting(
+                    PwmSetting.IP_PERMITTED_RANGE,
+                    null,
+                    DomainID.systemId() );
+            final Optional<StoredValue> storedValue = storedConfiguration.readStoredValue( interestedKey );
+            if ( storedValue.isPresent() )
+            {
+                final List<String> oldValues = ValueTypeConverter.valueToStringArray( storedValue.get() );
+                if ( !CollectionUtil.isEmpty( oldValues ) )
+                {
+                    final String firstValue = oldValues.get( 0 );
+                    final String errorMsg = "Deprecated configuration setting '"
+                            + PwmSetting.IP_PERMITTED_RANGE.toMenuLocationDebug( null, PwmConstants.DEFAULT_LOCALE )
+                            + "' has a value of '" + firstValue
+                            + "'.  This setting is no longer used, and the configuration must not contain a value for this setting.";
+                    throw PwmUnrecoverableException.newException( PwmError.CONFIG_FORMAT_ERROR, errorMsg );
+                }
+            }
+        }
+    }
+
+}

+ 0 - 1
server/src/main/java/password/pwm/config/stored/StoredConfigZipJsonSerializer.java

@@ -287,7 +287,6 @@ public class StoredConfigZipJsonSerializer implements StoredConfigSerializer
     }
 
     private String hash( final FileValue.FileContent fileContent )
-            throws PwmUnrecoverableException
     {
         return SecureEngine.hash( fileContent.getContents().newByteArrayInputStream(), PwmHashAlgorithm.SHA256 );
     }

+ 2 - 2
server/src/main/java/password/pwm/config/stored/StoredConfigurationUtil.java

@@ -80,7 +80,7 @@ public abstract class StoredConfigurationUtil
     {
         if ( !pwmSetting.getCategory().hasProfiles() && pwmSetting.getSyntax() != PwmSettingSyntax.PROFILE )
         {
-            throw new IllegalArgumentException( "cannot build profile list for non-profile setting " + pwmSetting.toString() );
+            throw new IllegalArgumentException( "cannot build profile list for non-profile setting " + pwmSetting );
         }
 
         final PwmSetting profileSetting;
@@ -116,7 +116,7 @@ public abstract class StoredConfigurationUtil
         final StoredValue storedValue = StoredConfigurationUtil.getValueOrDefault( storedConfiguration, key );
         final List<String> settingValues = ValueTypeConverter.valueToStringArray( storedValue );
         return settingValues.stream()
-                .filter( value -> StringUtil.notEmpty( value ) )
+                .filter( StringUtil::notEmpty )
                 .collect( Collectors.toUnmodifiableList() );
     }
 

+ 0 - 1
server/src/main/java/password/pwm/config/value/AbstractValue.java

@@ -91,7 +91,6 @@ public abstract class AbstractValue implements StoredValue
     }
 
     protected static String b64encode( final ImmutableByteArray immutableByteArray )
-            throws PwmUnrecoverableException
     {
         final String input = StringUtil.base64Encode( immutableByteArray.copyOf(), StringUtil.Base64Options.GZIP );
         return "\n" + StringUtil.insertRepeatedLineBreaks( input, PwmConstants.XML_OUTPUT_LINE_WRAP_LENGTH ) + "\n";

+ 0 - 2
server/src/main/java/password/pwm/config/value/CustomLinkValue.java

@@ -25,7 +25,6 @@ import org.jrivard.xmlchai.XmlElement;
 import password.pwm.config.PwmSetting;
 import password.pwm.config.stored.XmlOutputProcessData;
 import password.pwm.config.value.data.CustomLinkConfiguration;
-import password.pwm.error.PwmOperationalException;
 import password.pwm.util.json.JsonFactory;
 import password.pwm.util.secure.PwmSecurityKey;
 
@@ -70,7 +69,6 @@ public class CustomLinkValue extends AbstractValue implements StoredValue
 
             @Override
             public CustomLinkValue fromXmlElement( final PwmSetting pwmSetting, final XmlElement settingElement, final PwmSecurityKey key )
-                    throws PwmOperationalException
             {
                 final List<XmlElement> valueElements = settingElement.getChildren( "value" );
                 final List<CustomLinkConfiguration> values = new ArrayList<>();

+ 0 - 2
server/src/main/java/password/pwm/config/value/OptionListValue.java

@@ -24,7 +24,6 @@ import org.jrivard.xmlchai.XmlChai;
 import org.jrivard.xmlchai.XmlElement;
 import password.pwm.config.PwmSetting;
 import password.pwm.config.stored.XmlOutputProcessData;
-import password.pwm.error.PwmOperationalException;
 import password.pwm.util.json.JsonFactory;
 import password.pwm.util.secure.PwmSecurityKey;
 
@@ -70,7 +69,6 @@ public class OptionListValue extends AbstractValue implements StoredValue
 
             @Override
             public OptionListValue fromXmlElement( final PwmSetting pwmSetting, final XmlElement settingElement, final PwmSecurityKey key )
-                    throws PwmOperationalException
             {
                 final List<XmlElement> valueElements = settingElement.getChildren( "value" );
                 final Set<String> values = new TreeSet<>();

+ 2 - 2
server/src/main/java/password/pwm/config/value/StoredValueEncoder.java

@@ -198,7 +198,7 @@ public abstract class StoredValueEncoder
             {
                 final String errorMsg = "unable to decrypt config password value for setting: " + e.getMessage();
                 final ErrorInformation errorInfo = new ErrorInformation( PwmError.CONFIG_FORMAT_ERROR, errorMsg );
-                LOGGER.warn( () -> errorInfo.toDebugStr() );
+                LOGGER.warn( errorInfo::toDebugStr );
                 throw new PwmOperationalException( errorInfo );
             }
         }
@@ -250,7 +250,7 @@ public abstract class StoredValueEncoder
             {
                 final String errorMsg = "unable to decrypt password value for setting: " + e.getMessage();
                 final ErrorInformation errorInfo = new ErrorInformation( PwmError.CONFIG_FORMAT_ERROR, errorMsg );
-                LOGGER.warn( () -> errorInfo.toDebugStr() );
+                LOGGER.warn( errorInfo::toDebugStr );
                 throw new PwmOperationalException( errorInfo );
             }
         }

+ 0 - 2
server/src/main/java/password/pwm/config/value/UserPermissionValue.java

@@ -26,7 +26,6 @@ import password.pwm.config.PwmSetting;
 import password.pwm.config.stored.StoredConfigXmlConstants;
 import password.pwm.config.stored.XmlOutputProcessData;
 import password.pwm.config.value.data.UserPermission;
-import password.pwm.error.PwmOperationalException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.ldap.permission.UserPermissionType;
 import password.pwm.ldap.permission.UserPermissionUtility;
@@ -89,7 +88,6 @@ public class UserPermissionValue extends AbstractValue implements StoredValue
 
             @Override
             public UserPermissionValue fromXmlElement( final PwmSetting pwmSetting, final XmlElement settingElement, final PwmSecurityKey key )
-                    throws PwmOperationalException
             {
                 final boolean newType = "2".equals( settingElement.getAttribute( StoredConfigXmlConstants.XML_ATTRIBUTE_SYNTAX_VERSION )
                                 .orElse( "" ) );

+ 2 - 2
server/src/main/java/password/pwm/config/value/ValueTypeConverter.java

@@ -141,7 +141,7 @@ public final class ValueTypeConverter
     {
         if ( PwmSettingSyntax.ACTION != setting.getSyntax() )
         {
-            throw new IllegalArgumentException( "may not read ACTION value for setting: " + setting.toString() );
+            throw new IllegalArgumentException( "may not read ACTION value for setting: " + setting );
         }
 
         return ( List<ActionConfiguration> ) storedValue.toNativeObject();
@@ -151,7 +151,7 @@ public final class ValueTypeConverter
     {
         if ( PwmSettingSyntax.X509CERT != setting.getSyntax() )
         {
-            throw new IllegalArgumentException( "may not read X509CERT value for setting: " + setting.toString() );
+            throw new IllegalArgumentException( "may not read X509CERT value for setting: " + setting );
         }
 
         return ( (X509CertificateValue) storedValue ).asX509Certificates();

+ 0 - 2
server/src/main/java/password/pwm/config/value/VerificationMethodValue.java

@@ -27,7 +27,6 @@ import password.pwm.config.PwmSetting;
 import password.pwm.config.option.IdentityVerificationMethod;
 import password.pwm.config.stored.StoredConfigXmlConstants;
 import password.pwm.config.stored.XmlOutputProcessData;
-import password.pwm.error.PwmOperationalException;
 import password.pwm.i18n.Display;
 import password.pwm.util.i18n.LocaleHelper;
 import password.pwm.util.java.CollectionUtil;
@@ -140,7 +139,6 @@ public class VerificationMethodValue extends AbstractValue implements StoredValu
 
             @Override
             public VerificationMethodValue fromXmlElement( final PwmSetting pwmSetting, final XmlElement settingElement, final PwmSecurityKey key )
-                    throws PwmOperationalException
             {
                 final Optional<XmlElement> valueElement = settingElement.getChild( StoredConfigXmlConstants.XML_ELEMENT_VALUE );
                 if ( valueElement.isPresent() )

+ 2 - 2
server/src/main/java/password/pwm/health/ApplianceStatusChecker.java

@@ -141,7 +141,7 @@ public class ApplianceStatusChecker implements HealthSupplier
         if ( StringUtil.isEmpty( tokenFile ) )
         {
             final String msg = "unable to determine appliance token, token file environment param "
-                    + PwmEnvironment.ApplicationParameter.ApplianceTokenFile.toString() + " is not set";
+                    + PwmEnvironment.ApplicationParameter.ApplianceTokenFile + " is not set";
             throw new PwmOperationalException( new ErrorInformation( PwmError.ERROR_INTERNAL, msg ) );
         }
         final String fileInput = readFileContents( tokenFile );
@@ -159,7 +159,7 @@ public class ApplianceStatusChecker implements HealthSupplier
         if ( StringUtil.isEmpty( hostnameFile ) )
         {
             final String msg = "unable to determine appliance hostname, hostname file environment param "
-                    + PwmEnvironment.ApplicationParameter.ApplianceHostnameFile.toString() + " is not set";
+                    + PwmEnvironment.ApplicationParameter.ApplianceHostnameFile + " is not set";
             throw new PwmOperationalException( new ErrorInformation( PwmError.ERROR_INTERNAL, msg ) );
         }
 

+ 1 - 1
server/src/main/java/password/pwm/health/HealthMessage.java

@@ -136,7 +136,7 @@ public enum HealthMessage
 
     public String getKey( )
     {
-        return HealthMessage.class.getSimpleName() + "_" + this.toString();
+        return HealthMessage.class.getSimpleName() + "_" + this;
     }
 
     public String getDescription(

+ 1 - 1
server/src/main/java/password/pwm/health/HealthStatus.java

@@ -41,7 +41,7 @@ public enum HealthStatus
 
     public String getKey( )
     {
-        return HealthStatus.class.getSimpleName() + "_" + this.toString();
+        return HealthStatus.class.getSimpleName() + "_" + this;
     }
 
     public String getDescription( final Locale locale, final SettingReader config )

+ 1 - 1
server/src/main/java/password/pwm/health/HealthTopic.java

@@ -43,7 +43,7 @@ public enum HealthTopic
 
     public String getKey( )
     {
-        return HealthTopic.class.getSimpleName() + "_" + this.toString();
+        return HealthTopic.class.getSimpleName() + "_" + this;
     }
 
     public String getDescription( final Locale locale, final SettingReader config )

+ 1 - 1
server/src/main/java/password/pwm/health/LDAPHealthChecker.java

@@ -775,7 +775,7 @@ public class LDAPHealthChecker implements HealthSupplier
             // cache the error
             healthProperties.put( HealthService.HealthMonitorFlag.LdapVendorSameCheck, healthRecords );
 
-            LOGGER.warn( sessionLabel, () -> "multiple ldap vendors found: " + vendorMsg.toString() );
+            LOGGER.warn( sessionLabel, () -> "multiple ldap vendors found: " + vendorMsg );
         }
         else if ( discoveredVendors.size() == 1 )
         {

+ 2 - 2
server/src/main/java/password/pwm/http/ContextManager.java

@@ -484,11 +484,11 @@ public class ContextManager implements Serializable
                     try
                     {
                         Files.move( source, dest );
-                        LOGGER.info( SESSION_LABEL, () -> "file " + source.toString() + " has been renamed to " + dest.toString() );
+                        LOGGER.info( SESSION_LABEL, () -> "file " + source + " has been renamed to " + dest );
                     }
                     catch ( final IOException e )
                     {
-                        LOGGER.error( SESSION_LABEL, () -> "error renaming file " + source.toString() + " to " + dest.toString() + ", error: " + e.getMessage() );
+                        LOGGER.error( SESSION_LABEL, () -> "error renaming file " + source + " to " + dest + ", error: " + e.getMessage() );
                     }
                 }
             }

+ 1 - 1
server/src/main/java/password/pwm/http/JspUtility.java

@@ -203,7 +203,7 @@ public abstract class JspUtility
         {
             return LocaleHelper.valueNotApplicable( pwmRequest.getLocale() );
         }
-        return "<span class=\"timestamp\">" + instant.toString() + "</span>";
+        return "<span class=\"timestamp\">" + instant + "</span>";
     }
 
     public static String localizedString( final PageContext pageContext, final String key, final Class<? extends PwmDisplayBundle> bundleClass, final String... values )

+ 2 - 2
server/src/main/java/password/pwm/http/PwmResponse.java

@@ -157,7 +157,7 @@ public class PwmResponse extends PwmHttpResponseWrapper
         }
         catch ( final PwmUnrecoverableException e )
         {
-            LOGGER.error( () -> "unexpected error sending user to success page: " + e.toString() );
+            LOGGER.error( () -> "unexpected error sending user to success page: " + e );
         }
     }
 
@@ -202,7 +202,7 @@ public class PwmResponse extends PwmHttpResponseWrapper
             }
             catch ( final PwmUnrecoverableException e )
             {
-                LOGGER.error( () -> "unexpected error sending user to error page: " + e.toString() );
+                LOGGER.error( () -> "unexpected error sending user to error page: " + e );
             }
         }
         else

+ 2 - 2
server/src/main/java/password/pwm/http/SessionManager.java

@@ -249,11 +249,11 @@ public class SessionManager
                 final Permission.PermissionStatus finalStatus = status;
                 LOGGER.debug( pwmSession.getLabel(),
                         () -> String.format( "permission %s for user %s is %s",
-                                permission.toString(),
+                                permission,
                                 pwmSession.isAuthenticated()
                                         ? pwmSession.getUserInfo().getUserIdentity().toDelimitedKey()
                                         : "[unauthenticated]",
-                                finalStatus.toString() ) );
+                                finalStatus ) );
             }
         }
         return status == Permission.PermissionStatus.GRANTED;

+ 41 - 71
server/src/main/java/password/pwm/http/auth/CASFilterAuthenticationProvider.java

@@ -27,10 +27,9 @@ import org.jasig.cas.client.util.AbstractCasFilter;
 import org.jasig.cas.client.util.CommonUtils;
 import org.jasig.cas.client.util.XmlUtils;
 import org.jasig.cas.client.validation.Assertion;
-import password.pwm.PwmDomain;
 import password.pwm.PwmConstants;
+import password.pwm.PwmDomain;
 import password.pwm.config.PwmSetting;
-import password.pwm.config.value.FileValue;
 import password.pwm.config.value.FileValue.FileContent;
 import password.pwm.config.value.FileValue.FileInformation;
 import password.pwm.error.ErrorInformation;
@@ -61,6 +60,7 @@ import java.security.PrivateKey;
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.PKCS8EncodedKeySpec;
 import java.util.Map;
+import java.util.Optional;
 
 public class CASFilterAuthenticationProvider implements PwmHttpFilterAuthenticationProvider
 {
@@ -162,7 +162,7 @@ public class CASFilterAuthenticationProvider implements PwmHttpFilterAuthenticat
             final Map<FileInformation, FileContent> privatekey = pwmRequest.getDomainConfig().readSettingAsFile( PwmSetting.CAS_CLEARPASS_KEY );
             final String alg = pwmRequest.getDomainConfig().readSettingAsString( PwmSetting.CAS_CLEARPASS_ALGORITHM );
 
-            password = decryptPassword( alg, privatekey, encodedPsw );
+            password = decryptPassword( alg, privatekey, encodedPsw ).orElse( null );
         }
 
         // If using the old method
@@ -209,87 +209,57 @@ public class CASFilterAuthenticationProvider implements PwmHttpFilterAuthenticat
         return true;
     }
 
-    private static PasswordData decryptPassword( final String alg,
-                                                 final Map<FileInformation, FileContent> privatekey, final String encodedPsw )
+    private static Optional<PasswordData> decryptPassword(
+            final String alg,
+            final Map<FileInformation, FileContent> inputFileMap,
+            final String encodedPsw
+    )
     {
-        PasswordData password = null;
-
         if ( alg == null || alg.trim().isEmpty() )
         {
-            return password;
+            return Optional.empty();
         }
 
-        final byte[] privateKeyBytes;
-        if ( privatekey != null && !privatekey.isEmpty() )
-        {
-            final FileValue.FileContent fileContent = privatekey.values().iterator().next();
-            privateKeyBytes = fileContent.getContents().copyOf();
-        }
-        else
+        if ( inputFileMap == null || inputFileMap.isEmpty() )
         {
-            privateKeyBytes = null;
+            return Optional.empty();
         }
 
-        if ( privateKeyBytes != null )
+        final FileContent fileContent = inputFileMap.values().iterator().next();
+        final byte[] privateKeyBytes = fileContent.getContents().copyOf();
+
+        final PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec( privateKeyBytes );
+        try
         {
-            final PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec( privateKeyBytes );
-            try
+            final KeyFactory kf = KeyFactory.getInstance( alg );
+            final PrivateKey privateKey = kf.generatePrivate( spec );
+            final Cipher cipher = Cipher.getInstance( privateKey.getAlgorithm() );
+            final byte[] cred64 = StringUtil.base64Decode( encodedPsw );
+            cipher.init( Cipher.DECRYPT_MODE, privateKey );
+            final byte[] cipherData = cipher.doFinal( cred64 );
+            if ( cipherData != null )
             {
-                final KeyFactory kf = KeyFactory.getInstance( alg );
-                final PrivateKey privateKey = kf.generatePrivate( spec );
-                final Cipher cipher = Cipher.getInstance( privateKey.getAlgorithm() );
-                final byte[] cred64 = StringUtil.base64Decode( encodedPsw );
-                cipher.init( Cipher.DECRYPT_MODE, privateKey );
-                final byte[] cipherData = cipher.doFinal( cred64 );
-                if ( cipherData != null )
+                try
                 {
-                    try
-                    {
-                        password = new PasswordData( new String( cipherData, PwmConstants.DEFAULT_CHARSET ) );
-                    }
-                    catch ( final PwmUnrecoverableException e )
-                    {
-                        LOGGER.error( () -> "Decryption failed", e );
-                        return password;
-                    }
+                    return Optional.of( new PasswordData( new String( cipherData, PwmConstants.DEFAULT_CHARSET ) ) );
+                }
+                catch ( final PwmUnrecoverableException e )
+                {
+                    LOGGER.error( () -> "Decryption failed", e );
                 }
-            }
-            catch ( final NoSuchAlgorithmException e1 )
-            {
-                LOGGER.error( () -> "Decryption failed", e1 );
-                return password;
-            }
-            catch ( final InvalidKeySpecException e1 )
-            {
-                LOGGER.error( () -> "Decryption failed", e1 );
-                return password;
-            }
-            catch ( final NoSuchPaddingException e1 )
-            {
-                LOGGER.error( () -> "Decryption failed", e1 );
-                return password;
-            }
-            catch ( final IOException e1 )
-            {
-                LOGGER.error( () -> "Decryption failed", e1 );
-                return password;
-            }
-            catch ( final InvalidKeyException e1 )
-            {
-                LOGGER.error( () -> "Decryption failed", e1 );
-                return password;
-            }
-            catch ( final IllegalBlockSizeException e )
-            {
-                LOGGER.error( () -> "Decryption failed", e );
-                return password;
-            }
-            catch ( final BadPaddingException e )
-            {
-                LOGGER.error( () -> "Decryption failed", e );
-                return password;
             }
         }
-        return password;
+        catch ( final NoSuchAlgorithmException
+                | BadPaddingException
+                | IllegalBlockSizeException
+                | InvalidKeyException
+                | IOException
+                | NoSuchPaddingException
+                | InvalidKeySpecException e1 )
+        {
+            LOGGER.error( () -> "Decryption failed", e1 );
+        }
+
+        return Optional.empty();
     }
 }

+ 1 - 1
server/src/main/java/password/pwm/http/bean/SetupOtpBean.java

@@ -94,7 +94,7 @@ public class SetupOtpBean extends PwmSessionBean
             catch ( final NoSuchAlgorithmException | NoSuchProviderException ex )
             {
                 random = new SecureRandom();
-                LOGGER.error( () -> ex.getMessage(), ex );
+                LOGGER.error( ex::getMessage, ex );
             }
             random.setSeed( ( new Date() ).getTime() );
             challenge = random.nextLong() % ( 1_000_000 );

+ 1 - 1
server/src/main/java/password/pwm/http/filter/ApplicationModeFilter.java

@@ -69,7 +69,7 @@ public class ApplicationModeFilter extends AbstractPwmFilter
                 {
                     try
                     {
-                        LOGGER.error( () -> e.getMessage() );
+                        LOGGER.error( e::getMessage );
                     }
                     catch ( final Exception ignore )
                     {

+ 0 - 42
server/src/main/java/password/pwm/http/filter/RequestInitializationFilter.java

@@ -48,7 +48,6 @@ import password.pwm.svc.intruder.IntruderServiceClient;
 import password.pwm.svc.stats.EpsStatistic;
 import password.pwm.svc.stats.Statistic;
 import password.pwm.svc.stats.StatisticsService;
-import password.pwm.util.IPMatcher;
 import password.pwm.util.i18n.LocaleHelper;
 import password.pwm.util.java.StringUtil;
 import password.pwm.util.java.TimeDuration;
@@ -634,9 +633,6 @@ public class RequestInitializationFilter implements Filter
         // check headers
         checkRequiredHeaders( pwmRequest );
 
-        // check permitted source IP address
-        checkSourceNetworkAddress( pwmRequest );
-
         // csrf cross-site request forgery checks
         checkCsrfHeader( pwmRequest );
 
@@ -725,44 +721,6 @@ public class RequestInitializationFilter implements Filter
         }
     }
 
-    private static void checkSourceNetworkAddress( final PwmRequest pwmRequest )
-            throws PwmUnrecoverableException
-    {
-        final List<String> requiredHeaders = pwmRequest.getAppConfig().readSettingAsStringArray( PwmSetting.IP_PERMITTED_RANGE );
-        if ( requiredHeaders != null && !requiredHeaders.isEmpty() )
-        {
-            final String requestAddress = pwmRequest.getHttpServletRequest().getRemoteAddr();
-            for ( final String ipMatchString : requiredHeaders )
-            {
-                try
-                {
-                    final IPMatcher ipMatcher = new IPMatcher( ipMatchString );
-                    try
-                    {
-                        if ( ipMatcher.match( requestAddress ) )
-                        {
-                            return;
-
-                        }
-                    }
-                    catch ( final IPMatcher.IPMatcherException e )
-                    {
-                        LOGGER.error( () -> "error while attempting to match permitted address range '" + ipMatchString + "', error: " + e );
-                    }
-                }
-                catch ( final IPMatcher.IPMatcherException e )
-                {
-                    LOGGER.error( () -> "error parsing permitted address range '" + ipMatchString + "', error: " + e );
-                }
-            }
-
-            final String errorMsg = "request network address '" + requestAddress + "' does not match any configured permitted source address";
-            final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_SECURITY_VIOLATION, errorMsg );
-            throw new PwmUnrecoverableException( errorInformation );
-        }
-    }
-
-
     private static void checkCsrfHeader( final PwmRequest pwmRequest )
             throws PwmUnrecoverableException
     {

+ 2 - 2
server/src/main/java/password/pwm/http/servlet/GuestRegistrationServlet.java

@@ -562,11 +562,11 @@ public class GuestRegistrationServlet extends ControlledPwmServlet
 
         if ( expirationDate.isAfter( futureDate ) )
         {
-            final String errorMsg = "expiration date must be sooner than " + futureDate.toString();
+            final String errorMsg = "expiration date must be sooner than " + futureDate;
             throw new PwmOperationalException( new ErrorInformation( PwmError.ERROR_FIELD_REQUIRED, errorMsg ) );
         }
 
-        LOGGER.trace( pwmRequest, () -> "read expiration date as " + expirationDate.toString() );
+        LOGGER.trace( pwmRequest, () -> "read expiration date as " + expirationDate );
         return expirationDate;
     }
 

+ 1 - 1
server/src/main/java/password/pwm/http/servlet/LogoutServlet.java

@@ -245,7 +245,7 @@ public class LogoutServlet extends ControlledPwmServlet
             if ( matchedServlet != null )
             {
                 final PwmServletDefinition finalMatchedServlet = matchedServlet;
-                LOGGER.trace( pwmRequest, () -> "matched next url to servlet definition " + finalMatchedServlet.toString() );
+                LOGGER.trace( pwmRequest, () -> "matched next url to servlet definition " + finalMatchedServlet );
                 return Optional.of( basePath + matchedServlet.servletUrl() );
             }
             else

+ 1 - 1
server/src/main/java/password/pwm/http/servlet/configeditor/ConfigEditorServlet.java

@@ -763,7 +763,7 @@ public class ConfigEditorServlet extends ControlledPwmServlet
             modifier.writeSetting( key, fileValue.get(), userIdentity );
             configManagerBean.setStoredConfiguration( modifier.newStoredConfiguration() );
             pwmRequest.outputJsonResult( RestResultBean.forSuccessMessage( pwmRequest, Message.Success_Unknown ) );
-            LOGGER.trace( pwmRequest, () -> "file upload completed for setting " + key.toString() + ", file: "
+            LOGGER.trace( pwmRequest, () -> "file upload completed for setting " + key + ", file: "
                     + fileValue.get().toDebugJsonObject( pwmRequest.getLocale() ) );
         }
         else

+ 1 - 1
server/src/main/java/password/pwm/http/servlet/configguide/ConfigGuideServlet.java

@@ -503,7 +503,7 @@ public class ConfigGuideServlet extends ControlledPwmServlet
         {
             final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_INTERNAL, e.getMessage() );
             pwmRequest.outputJsonResult( RestResultBean.fromError( errorInformation, pwmRequest ) );
-            LOGGER.error( pwmRequest, () -> e.getMessage(), e );
+            LOGGER.error( pwmRequest, e::getMessage, e );
         }
 
         return ProcessStatus.Halt;

+ 2 - 2
server/src/main/java/password/pwm/http/servlet/configguide/ConfigGuideUtils.java

@@ -254,7 +254,7 @@ public class ConfigGuideUtils
                         throw new PwmOperationalException( new ErrorInformation( PwmError.CONFIG_FORMAT_ERROR, configErrors.get( 0 ) ) );
                     }
                     ConfigGuideUtils.writeConfig( ContextManager.getContextManager( req.getSession() ), storedConfig );
-                    LOGGER.trace( pwmRequest, () -> "read config from file: " + storedConfig.toString() );
+                    LOGGER.trace( pwmRequest, () -> "read config from file: " + storedConfig );
                     final RestResultBean restResultBean = RestResultBean.forSuccessMessage( pwmRequest, Message.Success_Unknown );
                     pwmRequest.getPwmResponse().outputJsonResult( restResultBean );
                     req.getSession().invalidate();
@@ -271,7 +271,7 @@ public class ConfigGuideUtils
                 final ErrorInformation errorInformation = new ErrorInformation( PwmError.CONFIG_UPLOAD_FAILURE, "error reading config file: no file present in upload" );
                 final RestResultBean restResultBean = RestResultBean.fromError( errorInformation, pwmRequest );
                 pwmRequest.getPwmResponse().outputJsonResult( restResultBean );
-                LOGGER.error( pwmRequest, () -> errorInformation.toDebugStr() );
+                LOGGER.error( pwmRequest, errorInformation::toDebugStr );
             }
         }
     }

+ 1 - 1
server/src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskServlet.java

@@ -374,7 +374,7 @@ public class HelpdeskServlet extends ControlledPwmServlet
         }
         catch ( final ChaiOperationException e )
         {
-            final String errorMsg = "error while attempting to delete user " + userIdentity.toString() + ", error: " + e.getMessage();
+            final String errorMsg = "error while attempting to delete user " + userIdentity + ", error: " + e.getMessage();
             final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_INTERNAL, errorMsg );
             LOGGER.debug( pwmRequest, () -> errorMsg );
             pwmRequest.outputJsonResult( RestResultBean.fromError( errorInformation, pwmRequest ) );

+ 1 - 1
server/src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskServletUtil.java

@@ -218,7 +218,7 @@ public class HelpdeskServletUtil
             final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_UNAUTHORIZED, errorMsg );
             throw new PwmUnrecoverableException( errorInformation );
         }
-        LOGGER.trace( pwmRequest, () -> "helpdesk detail view request for user details of " + userIdentity.toString() + " by actor " + actorUserIdentity.toString() );
+        LOGGER.trace( pwmRequest, () -> "helpdesk detail view request for user details of " + userIdentity.toString() + " by actor " + actorUserIdentity );
 
         final HelpdeskVerificationStateBean verificationStateBean = HelpdeskVerificationStateBean.fromClientString(
                 pwmRequest,

+ 2 - 2
server/src/main/java/password/pwm/http/servlet/oauth/OAuthConsumerServlet.java

@@ -189,7 +189,7 @@ public class OAuthConsumerServlet extends AbstractPwmServlet
             }
             catch ( final PwmUnrecoverableException e )
             {
-                final String errorMsg = "unexpected error redirecting user to oauth page: " + e.toString();
+                final String errorMsg = "unexpected error redirecting user to oauth page: " + e;
                 final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_OAUTH_ERROR, errorMsg );
                 setLastError( pwmRequest, errorInformation );
                 LOGGER.error( errorInformation::toDebugStr );
@@ -206,7 +206,7 @@ public class OAuthConsumerServlet extends AbstractPwmServlet
         }
         catch ( final PwmException e )
         {
-            final String errorMsg = "unexpected error communicating with oauth server: " + e.toString();
+            final String errorMsg = "unexpected error communicating with oauth server: " + e;
             final ErrorInformation errorInformation = new ErrorInformation( e.getError(), errorMsg );
             setLastError( pwmRequest, errorInformation );
             LOGGER.error( errorInformation::toDebugStr );

+ 1 - 1
server/src/main/java/password/pwm/http/servlet/peoplesearch/PhotoDataReader.java

@@ -200,7 +200,7 @@ public class PhotoDataReader
             if ( finalData.isPresent() )
             {
                 LOGGER.trace( pwmRequest, () -> "user photo data received for " + userIdentity.toDisplayString()
-                        + " " + finalData.get().toString()
+                        + " " + finalData.get()
                         + " (" + TimeDuration.compactFromCurrent( startTime ) + ")" );
             }
             else

+ 4 - 4
server/src/main/java/password/pwm/http/servlet/updateprofile/UpdateProfileServlet.java

@@ -331,7 +331,7 @@ public class UpdateProfileServlet extends ControlledPwmServlet
         }
         catch ( final PwmOperationalException e )
         {
-            LOGGER.error( pwmRequest, () -> e.getMessage() );
+            LOGGER.error( pwmRequest, e::getMessage );
             setLastError( pwmRequest, e.getErrorInformation() );
         }
 
@@ -401,7 +401,7 @@ public class UpdateProfileServlet extends ControlledPwmServlet
         }
         catch ( final PwmException e )
         {
-            LOGGER.error( pwmRequest, () -> e.getMessage() );
+            LOGGER.error( pwmRequest, e::getMessage );
             setLastError( pwmRequest, e.getErrorInformation() );
             UpdateProfileUtil.forwardToForm( pwmRequest, updateProfileProfile, updateProfileBean );
             return;
@@ -450,13 +450,13 @@ public class UpdateProfileServlet extends ControlledPwmServlet
         }
         catch ( final PwmException e )
         {
-            LOGGER.error( pwmRequest, () -> e.getMessage() );
+            LOGGER.error( pwmRequest, e::getMessage );
             setLastError( pwmRequest, e.getErrorInformation() );
         }
         catch ( final ChaiException e )
         {
             final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_UPDATE_ATTRS_FAILURE, e.toString() );
-            LOGGER.error( pwmRequest, () -> errorInformation.toDebugStr() );
+            LOGGER.error( pwmRequest, errorInformation::toDebugStr );
             setLastError( pwmRequest, errorInformation );
         }
 

+ 1 - 1
server/src/main/java/password/pwm/http/tag/conditional/PwmIfTag.java

@@ -95,7 +95,7 @@ public class PwmIfTag extends BodyTagSupport
                         }
                         catch ( final ChaiUnavailableException e )
                         {
-                            LOGGER.error( () -> "error testing jsp if '" + testEnum.toString() + "', error: " + e.getMessage() );
+                            LOGGER.error( () -> "error testing jsp if '" + testEnum + "', error: " + e.getMessage() );
                         }
                     }
                     else

+ 1 - 1
server/src/main/java/password/pwm/http/tag/url/PwmThemeURL.java

@@ -37,7 +37,7 @@ public enum PwmThemeURL
 
     public String token( )
     {
-        return "%" + this.toString() + "%";
+        return "%" + this + "%";
     }
 
     public String getCssName( )

+ 1 - 1
server/src/main/java/password/pwm/http/tag/value/PwmValueTag.java

@@ -105,7 +105,7 @@ public class PwmValueTag extends TagSupport
             }
             catch ( final Exception e )
             {
-                LOGGER.error( () -> "error executing value tag option '" + value.toString() + "', error: " + e.getMessage() );
+                LOGGER.error( () -> "error executing value tag option '" + value + "', error: " + e.getMessage() );
             }
         }
 

+ 49 - 26
server/src/main/java/password/pwm/ldap/LdapOperationsHelper.java

@@ -42,6 +42,7 @@ import password.pwm.bean.UserIdentity;
 import password.pwm.config.DomainConfig;
 import password.pwm.config.PwmSetting;
 import password.pwm.config.option.AutoSetLdapUserLanguage;
+import password.pwm.config.profile.AbstractProfile;
 import password.pwm.config.profile.LdapProfile;
 import password.pwm.config.value.data.FormConfiguration;
 import password.pwm.error.ErrorInformation;
@@ -226,7 +227,7 @@ public class LdapOperationsHelper
             }
         }
 
-        final String existingValue = GUIDHelper.readExistingGuidValue(
+        final String existingValue = GuidReaderUtil.readExistingGuidValue(
                 pwmDomain,
                 sessionLabel,
                 userIdentity,
@@ -242,11 +243,11 @@ public class LdapOperationsHelper
                 if ( ldapProfile.readSettingAsBoolean( PwmSetting.LDAP_GUID_AUTO_ADD ) )
                 {
                     LOGGER.trace( () -> "assigning new GUID to user " + userIdentity );
-                    return GUIDHelper.assignGuidToUser( pwmDomain, sessionLabel, userIdentity, guidAttributeName );
+                    return GuidReaderUtil.assignGuidToUser( pwmDomain, sessionLabel, userIdentity, guidAttributeName );
                 }
             }
-            final String errorMsg = "unable to resolve GUID value for user " + userIdentity.toString();
-            GUIDHelper.processError( errorMsg, throwExceptionOnError );
+            final String errorMsg = "unable to resolve GUID value for user " + userIdentity;
+            GuidReaderUtil.processError( errorMsg, throwExceptionOnError );
         }
 
         if ( enableCache )
@@ -429,7 +430,7 @@ public class LdapOperationsHelper
         }
     }
 
-    private static class GUIDHelper
+    private static class GuidReaderUtil
     {
         private static String readExistingGuidValue(
                 final PwmDomain pwmDomain,
@@ -441,35 +442,30 @@ public class LdapOperationsHelper
         {
             final ChaiUser theUser = pwmDomain.getProxiedChaiUser( sessionLabel, userIdentity );
             final LdapProfile ldapProfile = pwmDomain.getConfig().getLdapProfiles().get( userIdentity.getLdapProfileID() );
-            final String guidAttributeName = ldapProfile.readSettingAsString( PwmSetting.LDAP_GUID_ATTRIBUTE );
+            final AbstractProfile.GuidMode guidMode = ldapProfile.readGuidMode();
 
-            if ( "DN".equalsIgnoreCase( guidAttributeName ) )
+            if ( guidMode == AbstractProfile.GuidMode.DN )
             {
                 return userIdentity.toDelimitedKey();
             }
 
-            if ( "VENDORGUID".equalsIgnoreCase( guidAttributeName ) )
+            if ( guidMode == AbstractProfile.GuidMode.VENDORGUID )
             {
-                try
-                {
-                    final String guidValue = theUser.readGUID();
-                    if ( guidValue != null && guidValue.length() > 1 )
-                    {
-                        LOGGER.trace( sessionLabel, () -> "read VENDORGUID value for user " + theUser + ": " + guidValue );
-                    }
-                    else
-                    {
-                        LOGGER.trace( sessionLabel, () -> "unable to find a VENDORGUID value for user " + theUser.getEntryDN() );
-                    }
-                    return guidValue;
-                }
-                catch ( final Exception e )
-                {
-                    final String errorMsg = "error while reading vendor GUID value for user " + theUser.getEntryDN() + ", error: " + e.getMessage();
-                    return processError( errorMsg, throwExceptionOnError );
-                }
+               return readVendorGuid( theUser, sessionLabel, throwExceptionOnError );
             }
 
+           return readAttributeGuid( ldapProfile, userIdentity, theUser, throwExceptionOnError );
+        }
+
+        private static String readAttributeGuid(
+                final LdapProfile ldapProfile,
+                final UserIdentity userIdentity,
+                final ChaiUser theUser,
+                final boolean throwExceptionOnError
+        )
+                throws PwmUnrecoverableException
+        {
+            final String guidAttributeName = ldapProfile.readSettingAsString( PwmSetting.LDAP_GUID_ATTRIBUTE );
             try
             {
                 return theUser.readStringAttribute( guidAttributeName );
@@ -486,6 +482,33 @@ public class LdapOperationsHelper
             }
         }
 
+        private static String readVendorGuid(
+                final ChaiUser theUser,
+                final SessionLabel sessionLabel,
+                final boolean throwExceptionOnError
+        )
+                throws PwmUnrecoverableException
+        {
+            try
+            {
+                final String guidValue = theUser.readGUID();
+                if ( guidValue != null && guidValue.length() > 1 )
+                {
+                    LOGGER.trace( sessionLabel, () -> "read VENDORGUID value for user " + theUser + ": " + guidValue );
+                }
+                else
+                {
+                    LOGGER.trace( sessionLabel, () -> "unable to find a VENDORGUID value for user " + theUser.getEntryDN() );
+                }
+                return guidValue;
+            }
+            catch ( final Exception e )
+            {
+                final String errorMsg = "error while reading vendor GUID value for user " + theUser.getEntryDN() + ", error: " + e.getMessage();
+                return processError( errorMsg, throwExceptionOnError );
+            }
+        }
+
         private static String processError( final String errorMsg, final boolean throwExceptionOnError )
                 throws PwmUnrecoverableException
         {

+ 2 - 2
server/src/main/java/password/pwm/ldap/UserInfoReader.java

@@ -659,11 +659,11 @@ public class UserInfoReader implements UserInfo
                 if ( profileID.isPresent() )
                 {
                     returnMap.put( profileDefinition, profileID.get() );
-                    LOGGER.debug( sessionLabel, () -> "assigned " + profileDefinition.toString() + " profileID \"" + profileID.get() + "\" to " + userIdentity.toDisplayString() );
+                    LOGGER.debug( sessionLabel, () -> "assigned " + profileDefinition + " profileID \"" + profileID.get() + "\" to " + userIdentity.toDisplayString() );
                 }
                 else
                 {
-                    LOGGER.debug( sessionLabel, () -> profileDefinition.toString() + " has no matching profiles for user " + userIdentity.toDisplayString() );
+                    LOGGER.debug( sessionLabel, () -> profileDefinition + " has no matching profiles for user " + userIdentity.toDisplayString() );
                 }
             }
         }

+ 1 - 1
server/src/main/java/password/pwm/svc/PwmServiceManager.java

@@ -141,7 +141,7 @@ public class PwmServiceManager
         }
         catch ( final Exception e )
         {
-            final String errorMsg = "unexpected error instantiating service class '" + serviceName + "', error: " + e.toString();
+            final String errorMsg = "unexpected error instantiating service class '" + serviceName + "', error: " + e;
             LOGGER.fatal( () -> errorMsg, e );
             throw new PwmUnrecoverableException( new ErrorInformation( PwmError.ERROR_STARTUP_ERROR, errorMsg ) );
         }

+ 2 - 2
server/src/main/java/password/pwm/svc/cr/CrService.java

@@ -157,7 +157,7 @@ public class CrService extends AbstractPwmService implements PwmService
                     else
                     {
                         final ChallengeSet finalReturnSet = returnSet;
-                        LOGGER.debug( sessionLabel, () -> "using nmas c/r policy for user " + theUser.getEntryDN() + ": " + finalReturnSet.toString() );
+                        LOGGER.debug( sessionLabel, () -> "using nmas c/r policy for user " + theUser.getEntryDN() + ": " + finalReturnSet );
 
                         final String challengeID = "nmasPolicy-" + userIdentity.toDelimitedKey();
 
@@ -171,7 +171,7 @@ public class CrService extends AbstractPwmService implements PwmService
                         );
 
                         LOGGER.debug( sessionLabel, () -> "using ldap c/r policy for user " + theUser.getEntryDN() + ": "
-                                + finalReturnSet.toString() );
+                                + finalReturnSet );
                         LOGGER.trace( sessionLabel, () -> "readUserChallengeProfile completed, result=" + JsonFactory.get().serialize( challengeProfile ),
                                 () -> TimeDuration.fromCurrent( methodStartTime ) );
 

+ 5 - 5
server/src/main/java/password/pwm/svc/cr/NMASCrOperator.java

@@ -118,7 +118,7 @@ public class NMASCrOperator implements CrOperator
     private static final PwmLogger LOGGER = PwmLogger.forClass( NMASCrOperator.class );
 
     private final AtomicLoopIntIncrementer threadCounter = new AtomicLoopIntIncrementer();
-    private final List<NMASSessionThread> sessionMonitorThreads = Collections.synchronizedList( new ArrayList<NMASSessionThread>() );
+    private final List<NMASSessionThread> sessionMonitorThreads = Collections.synchronizedList( new ArrayList<>() );
     private final PwmDomain pwmDomain;
     private final TimeDuration maxThreadIdleTime;
     private final int maxThreadCount;
@@ -740,7 +740,7 @@ public class NMASCrOperator implements CrOperator
                 for ( final Callback callback : callbacks )
                 {
                     final String callbackClassname = callback.getClass().getName();
-                    LOGGER.trace( () -> "evaluating callback: " + callback.toString() + ", class=" + callbackClassname );
+                    LOGGER.trace( () -> "evaluating callback: " + callback + ", class=" + callbackClassname );
 
                     // note in some cases instanceof check fails due to classloader issues, using getName string comparison instead
                     if ( NMASCompletionCallback.class.getName().equals( callbackClassname ) )
@@ -774,7 +774,7 @@ public class NMASCrOperator implements CrOperator
                     else
                     {
                         unsupportedCallbackHasOccurred = true;
-                        LOGGER.trace( () -> "throwing UnsupportedCallbackException for " + callback.toString() + ", class=" + callback.getClass().getName() );
+                        LOGGER.trace( () -> "throwing UnsupportedCallbackException for " + callback + ", class=" + callback.getClass().getName() );
                         throw new UnsupportedCallbackException( callback );
                     }
                 }
@@ -983,7 +983,7 @@ public class NMASCrOperator implements CrOperator
                 }
                 else
                 {
-                    LOGGER.error( () -> "NMASLoginMonitor: LDAPException " + e.toString() );
+                    LOGGER.error( () -> "NMASLoginMonitor: LDAPException " + e );
                 }
                 setLoginState( NMASThreadState.COMPLETED );
                 final com.novell.security.nmas.client.NMASLoginResult localNMASLoginResult
@@ -1071,7 +1071,7 @@ public class NMASCrOperator implements CrOperator
             {
                 threadDebugInfo.append( "\n " ).append( thread.toDebugString() );
             }
-            LOGGER.trace( () -> threadDebugInfo.toString() );
+            LOGGER.trace( threadDebugInfo::toString );
         }
 
     }

+ 2 - 2
server/src/main/java/password/pwm/svc/db/DatabaseAccessorImpl.java

@@ -116,7 +116,7 @@ class DatabaseAccessorImpl implements DatabaseAccessor
 
             if ( exists )
             {
-                final String sqlText = "UPDATE " + table.toString()
+                final String sqlText = "UPDATE " + table
                         + " SET " + DatabaseService.VALUE_COLUMN + "=? WHERE "
                         + DatabaseService.KEY_COLUMN + "=?";
 
@@ -125,7 +125,7 @@ class DatabaseAccessorImpl implements DatabaseAccessor
             }
             else
             {
-                final String sqlText = "INSERT INTO " + table.toString()
+                final String sqlText = "INSERT INTO " + table
                         + "(" + DatabaseService.KEY_COLUMN + ", "
                         + DatabaseService.VALUE_COLUMN + ") VALUES(?,?)";
                 executeUpdate( sqlText, debugInfo, key, value );

+ 5 - 5
server/src/main/java/password/pwm/svc/db/DatabaseUtil.java

@@ -153,11 +153,11 @@ class DatabaseUtil
                 statement = connection.createStatement();
                 statement.execute( sqlString );
                 connection.commit();
-                LOGGER.debug( () -> "created table " + table.toString() );
+                LOGGER.debug( () -> "created table " + table );
             }
             catch ( final SQLException ex )
             {
-                final String errorMsg = "error creating new table " + table.toString() + ": " + ex.getMessage();
+                final String errorMsg = "error creating new table " + table + ": " + ex.getMessage();
                 final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_DB_UNAVAILABLE, errorMsg );
                 throw new DatabaseException( errorInformation );
             }
@@ -168,9 +168,9 @@ class DatabaseUtil
         }
 
         {
-            final String indexName = table.toString() + INDEX_NAME_SUFFIX;
+            final String indexName = table + INDEX_NAME_SUFFIX;
             final String sqlString = "CREATE index " + indexName
-                    + " ON " + table.toString()
+                    + " ON " + table
                     + " (" + DatabaseService.KEY_COLUMN + ")";
 
             Statement statement = null;
@@ -194,7 +194,7 @@ class DatabaseUtil
                 }
                 else
                 {
-                    LOGGER.warn( () -> errorInformation.toDebugStr() );
+                    LOGGER.warn( errorInformation::toDebugStr );
                 }
             }
             finally

+ 1 - 1
server/src/main/java/password/pwm/svc/intruder/IntruderDomainService.java

@@ -180,7 +180,7 @@ public class IntruderDomainService extends AbstractPwmService implements PwmServ
             final IntruderSettings.TypeSettings typeSettings = intruderSettings.getTargetSettings().get( type );
             if ( typeSettings.isConfigured() )
             {
-                LOGGER.debug( getSessionLabel(), () -> "starting record manager for type '" + type + "' with settings: " + typeSettings.toString() );
+                LOGGER.debug( getSessionLabel(), () -> "starting record manager for type '" + type + "' with settings: " + typeSettings );
                 recordManagers.put( type, new IntruderRecordManagerImpl( pwmDomain, type, recordStore, intruderSettings ) );
             }
             else

+ 5 - 5
server/src/main/java/password/pwm/svc/intruder/StubRecordManager.java

@@ -64,27 +64,27 @@ class StubRecordManager implements IntruderRecordManager
     @Override
     public ClosableIterator<IntruderRecord> iterator( ) throws PwmOperationalException
     {
-        return new ClosableIterator<IntruderRecord>()
+        return new ClosableIterator<>()
         {
             @Override
-            public boolean hasNext( )
+            public boolean hasNext()
             {
                 return false;
             }
 
             @Override
-            public IntruderRecord next( )
+            public IntruderRecord next()
             {
                 throw new NoSuchElementException();
             }
 
             @Override
-            public void remove( )
+            public void remove()
             {
             }
 
             @Override
-            public void close( )
+            public void close()
             {
             }
         };

+ 1 - 1
server/src/main/java/password/pwm/svc/otp/AbstractOtpOperator.java

@@ -75,7 +75,7 @@ public abstract class AbstractOtpOperator implements OtpOperator
                     value = OTPPamUtil.composePamData( otpUserRecord );
                     break;
                 default:
-                    final String errorStr = String.format( "Unsupported storage format: %s", format.toString() );
+                    final String errorStr = String.format( "Unsupported storage format: %s", format );
                     final ErrorInformation error = new ErrorInformation( PwmError.ERROR_INVALID_CONFIG, errorStr );
                     throw new PwmUnrecoverableException( error );
             }

+ 3 - 5
server/src/main/java/password/pwm/svc/otp/DbOtpOperator.java

@@ -81,7 +81,7 @@ public class DbOtpOperator extends AbstractOtpOperator
                         final OTPUserRecord otpConfig = decomposeOtpAttribute( decryptAttributeValue );
                         if ( otpConfig != null )
                         {
-                            LOGGER.debug( sessionLabel, () -> "found user OTP secret in db: " + otpConfig.toString() );
+                            LOGGER.debug( sessionLabel, () -> "found user OTP secret in db: " + otpConfig );
                             return Optional.of( otpConfig );
                         }
                     }
@@ -128,8 +128,7 @@ public class DbOtpOperator extends AbstractOtpOperator
         catch ( final PwmOperationalException ex )
         {
             final ErrorInformation errorInfo = new ErrorInformation( PwmError.ERROR_WRITING_OTP_SECRET, "unexpected error saving otp to db: " + ex.getMessage() );
-            final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException( errorInfo );
-            pwmOE.initCause( ex );
+            final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException( errorInfo, ex );
             throw pwmOE;
         }
     }
@@ -166,8 +165,7 @@ public class DbOtpOperator extends AbstractOtpOperator
                     PwmError.ERROR_WRITING_OTP_SECRET,
                     "unexpected error saving otp to db: " + ex.getMessage()
             );
-            final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException( errorInfo );
-            pwmOE.initCause( ex );
+            final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException( errorInfo, ex );
             throw pwmOE;
         }
     }

+ 2 - 4
server/src/main/java/password/pwm/svc/otp/LdapOtpOperator.java

@@ -148,8 +148,7 @@ public class LdapOtpOperator extends AbstractOtpOperator
                 errorMsg = "error writing OTP secret to ldap attribute '" + ldapStorageAttribute + "': " + ex.getMessage();
             }
             final ErrorInformation errorInfo = new ErrorInformation( PwmError.ERROR_WRITING_OTP_SECRET, errorMsg );
-            final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException( errorInfo );
-            pwmOE.initCause( ex );
+            final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException( errorInfo, ex );
             throw pwmOE;
         }
     }
@@ -192,8 +191,7 @@ public class LdapOtpOperator extends AbstractOtpOperator
                 errorMsg = "error clearing OTP secret to ldap attribute '" + ldapStorageAttribute + "': " + e.getMessage();
             }
             final ErrorInformation errorInfo = new ErrorInformation( PwmError.ERROR_WRITING_OTP_SECRET, errorMsg );
-            final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException( errorInfo );
-            pwmOE.initCause( e );
+            final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException( errorInfo, e );
             throw pwmOE;
         }
         catch ( final ChaiUnavailableException e )

+ 3 - 5
server/src/main/java/password/pwm/svc/otp/LocalDbOtpOperator.java

@@ -94,7 +94,7 @@ public class LocalDbOtpOperator extends AbstractOtpOperator
                         final OTPUserRecord otpConfig = decomposeOtpAttribute( decryptAttributeValue );
                         if ( otpConfig != null )
                         {
-                            LOGGER.debug( sessionLabel, () -> "found user OTP secret in LocalDB: " + otpConfig.toString() );
+                            LOGGER.debug( sessionLabel, () -> "found user OTP secret in LocalDB: " + otpConfig );
                             return Optional.of( otpConfig );
                         }
                     }
@@ -149,8 +149,7 @@ public class LocalDbOtpOperator extends AbstractOtpOperator
         catch ( final PwmOperationalException ex )
         {
             final ErrorInformation errorInfo = new ErrorInformation( PwmError.ERROR_WRITING_OTP_SECRET, "unexpected error saving otp to localDB: " + ex.getMessage() );
-            final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException( errorInfo );
-            pwmOE.initCause( ex );
+            final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException( errorInfo, ex );
             throw pwmOE;
         }
     }
@@ -185,8 +184,7 @@ public class LocalDbOtpOperator extends AbstractOtpOperator
         catch ( final LocalDBException ex )
         {
             final ErrorInformation errorInfo = new ErrorInformation( PwmError.ERROR_WRITING_OTP_SECRET, "unexpected error saving otp to localDB: " + ex.getMessage() );
-            final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException( errorInfo );
-            pwmOE.initCause( ex );
+            final PwmUnrecoverableException pwmOE = new PwmUnrecoverableException( errorInfo, ex );
             throw pwmOE;
         }
     }

+ 2 - 2
server/src/main/java/password/pwm/svc/otp/OtpService.java

@@ -413,7 +413,7 @@ public class OtpService extends AbstractPwmService implements PwmService
         if ( attempts != successes )
         {
             // should be impossible to read here, but just in case.
-            final String errorMsg = "OTP secret write only partially successful; attempts=" + attempts + ", successes=" + successes + ", errors: " + errorMsgs.toString();
+            final String errorMsg = "OTP secret write only partially successful; attempts=" + attempts + ", successes=" + successes + ", errors: " + errorMsgs;
             final ErrorInformation errorInfo = new ErrorInformation( PwmError.ERROR_WRITING_OTP_SECRET, errorMsg );
             throw new PwmOperationalException( errorInfo );
         }
@@ -474,7 +474,7 @@ public class OtpService extends AbstractPwmService implements PwmService
         if ( attempts != successes )
         {
             // should be impossible to read here, but just in case.
-            final String errorMsg = "OTP secret clearing only partially successful; attempts=" + attempts + ", successes=" + successes + ", error: " + errorMsgs.toString();
+            final String errorMsg = "OTP secret clearing only partially successful; attempts=" + attempts + ", successes=" + successes + ", error: " + errorMsgs;
             //@todo: replace error message
             final ErrorInformation errorInfo = new ErrorInformation( PwmError.ERROR_WRITING_OTP_SECRET, errorMsg );
             throw new PwmOperationalException( errorInfo );

+ 1 - 8
server/src/main/java/password/pwm/svc/otp/PasscodeGenerator.java

@@ -87,14 +87,7 @@ public class PasscodeGenerator
      */
     public PasscodeGenerator( final Mac mac, final int passCodeLength, final int interval )
     {
-        this( new Signer()
-        {
-            @Override
-            public byte[] sign( final byte[] data )
-            {
-                return mac.doFinal( data );
-            }
-        }, passCodeLength, interval );
+        this( mac::doFinal, passCodeLength, interval );
     }
 
     public PasscodeGenerator( final Signer signer, final int passCodeLength, final int interval )

+ 1 - 1
server/src/main/java/password/pwm/svc/secure/AbstractSecureService.java

@@ -139,7 +139,7 @@ public abstract class AbstractSecureService extends AbstractPwmService implement
     public ServiceInfoBean serviceInfo( )
     {
         return ServiceInfoBean.builder()
-                .debugProperties( CollectionUtil.combineMaps( List.of(
+                .debugProperties( CollectionUtil.combineOrderedMaps( List.of(
                         stats.debugStats(),
                         CollectionUtil.enumMapToStringMap( debugData() ) ) ) )
                 .build();

+ 2 - 2
server/src/main/java/password/pwm/svc/sms/SmsQueueService.java

@@ -245,13 +245,13 @@ public class SmsQueueService extends AbstractPwmService implements PwmService
 
         if ( smsItem.getTo() == null || smsItem.getTo().length() < 1 )
         {
-            LOGGER.debug( () -> "discarding sms send event (no to address) " + smsItem.toString() );
+            LOGGER.debug( () -> "discarding sms send event (no to address) " + smsItem );
             return false;
         }
 
         if ( smsItem.getMessage() == null || smsItem.getMessage().length() < 1 )
         {
-            LOGGER.debug( () -> "discarding sms send event (no message) " + smsItem.toString() );
+            LOGGER.debug( () -> "discarding sms send event (no message) " + smsItem );
             return false;
         }
 

+ 13 - 17
server/src/main/java/password/pwm/svc/wordlist/SharedHistoryService.java

@@ -79,7 +79,7 @@ public class SharedHistoryService extends AbstractPwmService implements PwmServi
 
     private LocalDB localDB;
     private String salt;
-    private long oldestEntry;
+    private Instant oldestEntry;
 
     private Settings settings = Settings.builder().build();
     private final Lock addWordLock = new ReentrantLock();
@@ -142,11 +142,7 @@ public class SharedHistoryService extends AbstractPwmService implements PwmServi
 
     public Instant getOldestEntryTime( )
     {
-        if ( size() > 0 )
-        {
-            return Instant.ofEpochMilli( oldestEntry );
-        }
-        return null;
+       return oldestEntry;
     }
 
     public long size( )
@@ -212,12 +208,12 @@ public class SharedHistoryService extends AbstractPwmService implements PwmServi
             final Optional<String> oldestEntryStr = localDB.get( META_DB, KEY_OLDEST_ENTRY );
             if ( oldestEntryStr.isPresent() )
             {
-                oldestEntry = Long.parseLong( oldestEntryStr.get() );
+                oldestEntry = Instant.ofEpochMilli( Long.parseLong( oldestEntryStr.get() ) );
                 LOGGER.trace( getSessionLabel(), () -> "oldest timestamp loaded from localDB, age is " + TimeDuration.fromCurrent( oldestEntry ).asCompactString() );
             }
             else
             {
-                oldestEntry = 0;
+                oldestEntry = Instant.now();
                 LOGGER.trace( getSessionLabel(), () -> "no oldestEntry timestamp stored, will rescan" );
                 }
         }
@@ -359,12 +355,12 @@ public class SharedHistoryService extends AbstractPwmService implements PwmServi
                 return;
             }
 
-            final long oldestEntryAge = System.currentTimeMillis() - oldestEntry;
+            final TimeDuration oldestEntryAge = TimeDuration.fromCurrent( oldestEntry );
             if ( settings.getMaxAge().isLongerThan( oldestEntryAge ) )
 
                 {
                 LOGGER.debug( getSessionLabel(), () -> "skipping wordDB reduce operation, eldestEntry="
-                        + TimeDuration.asCompactString( oldestEntryAge )
+                        + oldestEntryAge.asCompactString()
                         + ", maxAge="
                         + settings.getMaxAge().asCompactString() );
                 return;
@@ -373,7 +369,7 @@ public class SharedHistoryService extends AbstractPwmService implements PwmServi
             final Instant startTime = Instant.now();
             final long initialSize = size();
             int removeCount = 0;
-            long localOldestEntry = System.currentTimeMillis();
+            Instant localOldestEntry = Instant.now();
 
             LOGGER.debug( getSessionLabel(), () -> "beginning wordDB reduce operation, examining " + initialSize
                     + " words for entries older than " + settings.getMaxAge().asCompactString() );
@@ -386,10 +382,9 @@ public class SharedHistoryService extends AbstractPwmService implements PwmServi
                     final Map.Entry<String, String> entry = keyIterator.next();
                     final String key = entry.getKey();
                     final String value = entry.getValue();
-                    final long timeStamp = Long.parseLong( value );
-                    final long entryAge = System.currentTimeMillis() - timeStamp;
+                    final Instant entryTimestamp = Instant.ofEpochMilli( Long.parseLong( value ) );
 
-                    if ( settings.getMaxAge().isLongerThan( entryAge ) )
+                    if ( settings.getMaxAge().isLongerThan( TimeDuration.fromCurrent( entryTimestamp ) ) )
                     {
                         localDB.remove( WORDS_DB, key );
                         removeCount++;
@@ -402,7 +397,7 @@ public class SharedHistoryService extends AbstractPwmService implements PwmServi
                     }
                     else
                     {
-                        localOldestEntry = timeStamp < localOldestEntry ? timeStamp : localOldestEntry;
+                        localOldestEntry = localOldestEntry.isBefore( entryTimestamp ) ? entryTimestamp : localOldestEntry;
                     }
                 }
             }
@@ -411,14 +406,14 @@ public class SharedHistoryService extends AbstractPwmService implements PwmServi
             if ( status() == STATUS.OPEN )
             {
                 oldestEntry = localOldestEntry;
-                localDB.put( META_DB, KEY_OLDEST_ENTRY, Long.toString( oldestEntry ) );
+                localDB.put( META_DB, KEY_OLDEST_ENTRY, Long.toString( oldestEntry.getEpochSecond() ) );
             }
 
             {
                 final int finalRemove = removeCount;
                 LOGGER.debug( getSessionLabel(), () -> "completed wordDB reduce operation" + ", removed=" + finalRemove
                         + ", totalRemaining=" + size()
-                        + ", oldestEntry=" + TimeDuration.asCompactString( oldestEntry )
+                        + ", oldestEntry=" + oldestEntry
                         + " in ", () -> TimeDuration.fromCurrent( startTime ) );
             }
         }
@@ -527,4 +522,5 @@ public class SharedHistoryService extends AbstractPwmService implements PwmServi
             return ServiceInfoBean.builder().build();
         }
     }
+
 }

+ 0 - 352
server/src/main/java/password/pwm/util/IPMatcher.java

@@ -1,352 +0,0 @@
-/*
- * Password Management Servlets (PWM)
- * http://www.pwm-project.org
- *
- * Copyright (c) 2006-2009 Novell, Inc.
- * Copyright (c) 2009-2021 The PWM Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package password.pwm.util;
-
-import java.net.Inet6Address;
-import java.net.UnknownHostException;
-
-public class IPMatcher
-{
-    /**
-     * Network to match.
-     */
-    private byte[] network;
-
-    /**
-     * Network mask.
-     */
-    private byte[] netmask;
-
-    /**
-     * Construct an IPMatcher that will test for the given IP specification.
-     *
-     * @param ipSpec IP specification (full or partial address, network/netmask,
-     *               network/cidr)
-     * @throws IPMatcherException if there is an error parsing the specification (i.e. it is
-     *                            somehow malformed)
-     */
-    public IPMatcher( final String ipSpec ) throws IPMatcherException
-    {
-        // Boil all specs down to network + mask
-
-        String ipPart = ipSpec;
-        final String[] parts = ipSpec.split( "/" );
-
-        if ( parts[ 0 ].indexOf( ':' ) >= 0 )
-        {
-            // looks like IPv6
-            try
-            {
-                network = Inet6Address.getByName( parts[ 0 ] ).getAddress();
-            }
-            catch ( final UnknownHostException e )
-            {
-                throw new IPMatcherException(
-                        "Malformed IP range specification " + ipSpec, e );
-            }
-
-            netmask = new byte[ 16 ];
-            switch ( parts.length )
-            {
-                case 2:
-                    // CIDR notation:  calculate the mask
-                    final int maskBits;
-                    try
-                    {
-                        maskBits = Integer.parseInt( parts[ 1 ] );
-                    }
-                    catch ( final NumberFormatException nfe )
-                    {
-                        throw new IPMatcherException(
-                                "Malformed IP range specification " + ipSpec, nfe );
-                    }
-                    if ( maskBits < 0 || maskBits > 128 )
-                    {
-                        throw new IPMatcherException( "Mask bits out of range 0-128 "
-                                + ipSpec );
-                    }
-
-                    final int maskBytes = maskBits / 8;
-                    for ( int i = 0; i < maskBytes; i++ )
-                    {
-                        netmask[ i ] = ( byte ) 0Xff;
-                    }
-                    netmask[ maskBytes ] = ( byte ) ( ( byte ) 0Xff << 8 - ( maskBits % 8 ) );
-                    for ( int i = maskBytes + 1; i < ( 128 / 8 ); i++ )
-                    {
-                        netmask[ i ] = 0;
-                    }
-                    break;
-                case 1:
-                    // No explicit mask:  fill the mask with 1s
-                    for ( int i = 0; i < netmask.length; i++ )
-                    {
-                        netmask[ i ] = ( byte ) 0Xff;
-                    }
-                    break;
-                default:
-                    throw new IPMatcherException( "Malformed IP range specification "
-                            + ipSpec );
-            }
-        }
-        else
-        {
-            // assume IPv4
-            // Allow partial IP
-            boolean mustHave4 = false;
-
-            network = new byte[ 4 ];
-            netmask = new byte[ 4 ];
-            switch ( parts.length )
-            {
-                case 2:
-                    // Some kind of slash notation -- we'll need a full network IP
-                    ipPart = parts[ 0 ];
-                    mustHave4 = true;
-
-                    final String[] maskParts = parts[ 1 ].split( "\\." );
-                    if ( maskParts.length == 1 )
-                    {
-                        // CIDR slash notation
-                        final int x;
-
-                        try
-                        {
-                            x = Integer.parseInt( maskParts[ 0 ] );
-                        }
-                        catch ( final NumberFormatException nfe )
-                        {
-                            throw new IPMatcherException(
-                                    "Malformed IP range specification " + ipSpec, nfe );
-                        }
-
-                        if ( x < 0 || x > 32 )
-                        {
-                            throw new IPMatcherException();
-                        }
-
-                        final int fullMask = -1 << ( 32 - x );
-                        netmask[ 0 ] = ( byte ) ( ( fullMask & 0xFF000000 ) >>> 24 );
-                        netmask[ 1 ] = ( byte ) ( ( fullMask & 0x00FF0000 ) >>> 16 );
-                        netmask[ 2 ] = ( byte ) ( ( fullMask & 0x0000FF00 ) >>> 8 );
-                        netmask[ 3 ] = ( byte ) ( fullMask & 0x000000FF );
-                        ipToBytes( ipPart, network, mustHave4 );
-                    }
-                    else
-                    {
-                        // full subnet specified
-                        ipToBytes( parts[ 0 ], network, true );
-                        ipToBytes( parts[ 1 ], netmask, true );
-                    }
-                    break;
-
-                case 1:
-                    // Get IP
-                    for ( int i = 0; i < netmask.length; i++ )
-                    {
-                        netmask[ i ] = -1;
-                    }
-                    final int partCount = ipToBytes( ipPart, network, mustHave4 );
-
-                    // If partial IP, set mask for remaining bytes
-                    for ( int i = 3; i >= partCount; i-- )
-                    {
-                        netmask[ i ] = 0;
-                    }
-
-                    break;
-
-                default:
-                    throw new IPMatcherException( "Malformed IP range specification "
-                            + ipSpec );
-            }
-            network = ip4ToIp6( network );
-            netmask = ip4MaskToIp6( netmask );
-        }
-    }
-
-    /**
-     * Fill out a given four-byte array with the IPv4 address specified in the
-     * given String.
-     *
-     * @param ip        IPv4 address as a dot-delimited String
-     * @param bytes     4-byte array to fill out
-     * @param mustHave4 if true, will require that the given IP string specify all
-     *                  four bytes
-     * @return the number of actual IP bytes found in the given IP address
-     *         String
-     * @throws IPMatcherException if there is a problem parsing the IP string -- e.g. number
-     *                            outside of range 0-255, too many numbers, less than 4 numbers
-     *                            if {@code mustHave4} is true
-     */
-    private static int ipToBytes( final String ip, final byte[] bytes, final boolean mustHave4 )
-            throws IPMatcherException
-    {
-        final String[] parts = ip.split( "\\." );
-
-        if ( parts.length > 4 || mustHave4 && parts.length != 4 )
-        {
-            throw new IPMatcherException( "Malformed IP specification " + ip );
-        }
-
-        try
-        {
-
-            for ( int i = 0; i < parts.length; i++ )
-            {
-                final int p = Integer.parseInt( parts[ i ] );
-                if ( p < 0 || p > 255 )
-                {
-                    throw new IPMatcherException( "Malformed IP specification "
-                            + ip );
-
-                }
-
-                bytes[ i ] = ( byte ) ( p < 128 ? p : p - 256 );
-            }
-        }
-        catch ( final NumberFormatException nfe )
-        {
-            throw new IPMatcherException( "Malformed IP specification " + ip,
-                    nfe );
-        }
-
-        return parts.length;
-    }
-
-    /**
-     * Determine whether the given full IP falls within the range this
-     * {@code IPMatcher} was initialized with.
-     *
-     * @param ipIn IP address as dot-delimited String
-     * @return {@code true} if the IP matches the range of this
-     *         {@code IPMatcher}; {@code false} otherwise
-     * @throws IPMatcherException if the IP passed in cannot be parsed correctly (i.e. is
-     *                            malformed)
-     */
-    public boolean match( final String ipIn ) throws IPMatcherException
-    {
-        byte[] candidate;
-
-        if ( ipIn.indexOf( ':' ) < 0 )
-        {
-            candidate = new byte[ 4 ];
-            ipToBytes( ipIn, candidate, true );
-            candidate = ip4ToIp6( candidate );
-        }
-        else
-        {
-            try
-            {
-                candidate = Inet6Address.getByName( ipIn ).getAddress();
-            }
-            catch ( final UnknownHostException e )
-            {
-                throw new IPMatcherException( "Malformed IPv6 address ", e );
-            }
-        }
-
-        for ( int i = 0; i < netmask.length; i++ )
-        {
-            if ( ( candidate[ i ] & netmask[ i ] ) != ( network[ i ] & netmask[ i ] ) )
-            {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * Convert an IPv4 address to an IPv6 IPv4-compatible address.
-     *
-     * @param ip4 an IPv4 address
-     * @return the corresponding IPv6 address
-     * @throws IllegalArgumentException if ip4 is not exactly four octets long.
-     */
-    private static byte[] ip4ToIp6( final byte[] ip4 )
-    {
-        if ( ip4.length != 4 )
-        {
-            throw new IllegalArgumentException( "IPv4 address must be four octets" );
-        }
-
-        final byte[] ip6 = new byte[ 16 ];
-        for ( int i = 0; i < 16 - 4; i++ )
-        {
-            ip6[ i ] = 0;
-        }
-        for ( int i = 0; i < 4; i++ )
-        {
-            ip6[ 12 + i ] = ip4[ i ];
-        }
-        return ip6;
-    }
-
-    /**
-     * Convert an IPv4 mask to the equivalent IPv6 mask.
-     *
-     * @param ip4 an IPv4 mask
-     * @return the corresponding IPv6 mask
-     * @throws IllegalArgumentException if ip4 is not exactly four octets long.
-     */
-    private static byte[] ip4MaskToIp6( final byte[] ip4 )
-    {
-        if ( ip4.length != 4 )
-        {
-            throw new IllegalArgumentException( "IPv4 mask must be four octets" );
-        }
-
-        final byte[] ip6 = new byte[ 16 ];
-        for ( int i = 0; i < 16 - 4; i++ )
-        {
-            ip6[ i ] = ( byte ) 0Xff;
-        }
-        for ( int i = 0; i < 4; i++ )
-        {
-            ip6[ 12 + i ] = ip4[ i ];
-        }
-        return ip6;
-    }
-
-    public static class IPMatcherException extends Exception
-    {
-        public IPMatcherException( )
-        {
-            super();
-        }
-
-        public IPMatcherException( final String message )
-        {
-            super( message );
-        }
-
-        public IPMatcherException( final Throwable cause )
-        {
-            super( cause );
-        }
-
-        public IPMatcherException( final String message, final Throwable cause )
-        {
-            super( message, cause );
-        }
-    }
-}

+ 1 - 1
server/src/main/java/password/pwm/util/cli/MainClass.java

@@ -365,7 +365,7 @@ public class MainClass
         {
             final String errorMsg = "unable to establish operating environment: " + e.getMessage();
             final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_ENVIRONMENT_ERROR, errorMsg );
-            LOGGER.error( () -> errorInformation.toDebugStr(), e );
+            LOGGER.error( errorInformation::toDebugStr, e );
             out( "unable to establish operating environment: " + e.getMessage() );
             System.exit( -1 );
             return;

+ 1 - 1
server/src/main/java/password/pwm/util/debug/AboutItemGenerator.java

@@ -36,7 +36,7 @@ class AboutItemGenerator implements AppItemGenerator
     }
 
     @Override
-    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream ) throws Exception
+    public void outputItem( final AppDebugItemInput debugItemInput, final OutputStream outputStream )
     {
         final Map<PwmAboutProperty, String> infoBeanMap = PwmAboutProperty.makeInfoBean( debugItemInput.getPwmApplication() );
         final String jsonValue = JsonFactory.get().serializeMap( infoBeanMap, JsonProvider.Flag.PrettyPrint );

+ 1 - 1
server/src/main/java/password/pwm/util/debug/DebugItemGenerator.java

@@ -209,7 +209,7 @@ public class DebugItemGenerator
         }
         catch ( final Throwable e )
         {
-            final String errorMsg = "unexpected error executing debug item output class '" + serviceClass.getName() + "', error: " + e.toString();
+            final String errorMsg = "unexpected error executing debug item output class '" + serviceClass.getName() + "', error: " + e;
             LOGGER.error( sessionLabel, () -> errorMsg, e );
             debugGeneratorLogFile.appendLine( errorMsg );
             debugGeneratorLogFile.appendLine( JavaHelper.stackTraceToString( e ) );

+ 1 - 1
server/src/main/java/password/pwm/util/form/FormUtility.java

@@ -295,7 +295,7 @@ public class FormUtility
 
         final CacheService cacheService = pwmDomain.getCacheService();
         final CacheKey cacheKey = CacheKey.newKey(
-                Validator.class, null, "attr_unique_check_" + filter.toString()
+                Validator.class, null, "attr_unique_check_" + filter
         );
         if ( allowResultCaching && cacheService != null )
         {

+ 1 - 1
server/src/main/java/password/pwm/util/i18n/LocaleHelper.java

@@ -177,7 +177,7 @@ public class LocaleHelper
     {
         if ( !PwmDisplayBundle.class.isAssignableFrom( bundleClass ) )
         {
-            LOGGER.warn( () -> "attempt to resolve locale for non-DisplayBundleMarker class type " + bundleClass.toString() );
+            LOGGER.warn( () -> "attempt to resolve locale for non-DisplayBundleMarker class type " + bundleClass );
             return null;
         }
 

+ 4 - 4
server/src/main/java/password/pwm/util/i18n/LocaleStats.java

@@ -202,7 +202,7 @@ public class LocaleStats
             {
                 if ( DEBUG_FLAG )
                 {
-                    LOGGER.trace( () -> "missing resource bundle: bundle=" + pwmLocaleBundle.getTheClass().getName() + ", locale=" + locale.toString() );
+                    LOGGER.trace( () -> "missing resource bundle: bundle=" + pwmLocaleBundle.getTheClass().getName() + ", locale=" + locale );
                 }
                 returnList.addAll( pwmLocaleBundle.getDisplayKeys() );
             }
@@ -216,7 +216,7 @@ public class LocaleStats
                     {
                         if ( DEBUG_FLAG )
                         {
-                            LOGGER.trace( () -> "missing resource: bundle=" + pwmLocaleBundle.getTheClass().toString() + ", locale=" + locale.toString() + "' key=" + key );
+                            LOGGER.trace( () -> "missing resource: bundle=" + pwmLocaleBundle.getTheClass() + ", locale=" + locale + "' key=" + key );
                         }
                         returnList.add( key );
                     }
@@ -227,8 +227,8 @@ public class LocaleStats
         {
             if ( DEBUG_FLAG )
             {
-                LOGGER.trace( () -> "error loading resource bundle for class='" + pwmLocaleBundle.getTheClass().toString()
-                        + ", locale=" + locale.toString() + "', error: " + e.getMessage() );
+                LOGGER.trace( () -> "error loading resource bundle for class='" + pwmLocaleBundle.getTheClass()
+                        + ", locale=" + locale + "', error: " + e.getMessage() );
             }
         }
         Collections.sort( returnList );

+ 5 - 5
server/src/main/java/password/pwm/util/localdb/AbstractJDBCLocalDB.java

@@ -101,11 +101,11 @@ public abstract class AbstractJDBCLocalDB implements LocalDBProvider
                     statement = connection.createStatement();
                     statement.execute( sqlString );
                     connection.commit();
-                    LOGGER.debug( () -> "created table " + db.toString() + " (" + TimeDuration.fromCurrent( startTime ).asCompactString() + ")" );
+                    LOGGER.debug( () -> "created table " + db + " (" + TimeDuration.fromCurrent( startTime ).asCompactString() + ")" );
                 }
                 catch ( final SQLException ex )
                 {
-                    LOGGER.error( () -> "error creating new table " + db.toString() + ": " + ex.getMessage() );
+                    LOGGER.error( () -> "error creating new table " + db + ": " + ex.getMessage() );
                 }
                 finally
                 {
@@ -115,7 +115,7 @@ public abstract class AbstractJDBCLocalDB implements LocalDBProvider
 
             {
                 final Instant startTime = Instant.now();
-                final String indexName = db.toString() + "_IDX";
+                final String indexName = db + "_IDX";
                 final StringBuilder sqlString = new StringBuilder();
                 sqlString.append( "CREATE index " ).append( indexName );
                 sqlString.append( " ON " ).append( db );
@@ -327,7 +327,7 @@ public abstract class AbstractJDBCLocalDB implements LocalDBProvider
         PreparedStatement removeStatement = null;
 
         final String removeSqlString = "DELETE FROM " + db.toString() + " WHERE " + KEY_COLUMN + "=?";
-        final String insertSqlString = "INSERT INTO " + db.toString() + "(" + KEY_COLUMN + ", " + VALUE_COLUMN + ") VALUES(?,?)";
+        final String insertSqlString = "INSERT INTO " + db + "(" + KEY_COLUMN + ", " + VALUE_COLUMN + ") VALUES(?,?)";
 
         try
         {
@@ -437,7 +437,7 @@ public abstract class AbstractJDBCLocalDB implements LocalDBProvider
 
                 if ( !valueExists )
                 {
-                    final String insertSql = "INSERT INTO " + db.toString() + "(" + KEY_COLUMN + ", " + VALUE_COLUMN + ") VALUES(?,?)";
+                    final String insertSql = "INSERT INTO " + db + "(" + KEY_COLUMN + ", " + VALUE_COLUMN + ") VALUES(?,?)";
                     insertStatement = dbConnection.prepareStatement( insertSql );
                     insertStatement.setString( 1, key );
                     insertStatement.setString( 2, value );

+ 1 - 1
server/src/main/java/password/pwm/util/localdb/LocalDBUtility.java

@@ -119,7 +119,7 @@ public class LocalDBUtility
             {
                 if ( loopDB.isBackup() )
                 {
-                    csvPrinter.printComment( "Export of " + loopDB.toString() );
+                    csvPrinter.printComment( "Export of " + loopDB );
                     try ( LocalDB.LocalDBIterator<Map.Entry<String, String>> localDBIterator = localDB.iterator( loopDB ) )
                     {
                         while ( localDBIterator.hasNext() )

+ 1 - 1
server/src/main/java/password/pwm/util/logging/PwmLogger.java

@@ -560,7 +560,7 @@ public class PwmLogger
             while ( length > 0 )
             {
                 final String line = buffer.substring( 0, length );
-                buffer.delete( 0, +length + 1 );
+                buffer.delete( 0, length + 1 );
                 doLogEvent( logLevel, sessionLabel, () -> line, null );
                 length = buffer.indexOf( "\n" );
             }

+ 3 - 3
server/src/main/java/password/pwm/util/macro/StaticMacros.java

@@ -159,7 +159,7 @@ public abstract class StaticMacros
                         return StringUtil.base64Encode( input.getBytes( PwmConstants.DEFAULT_CHARSET ) );
 
                     default:
-                        throw new MacroParseException( "unimplemented encodeType '" + this.toString() + "' for Encode macro" );
+                        throw new MacroParseException( "unimplemented encodeType '" + this + "' for Encode macro" );
                 }
             }
 
@@ -251,7 +251,7 @@ public abstract class StaticMacros
                         return doHash( input, PwmHashAlgorithm.SHA512 );
 
                     default:
-                        throw new MacroParseException( "unimplemented hashtype '" + this.toString() + "' for Hash macro" );
+                        throw new MacroParseException( "unimplemented hashtype '" + this + "' for Hash macro" );
                 }
             }
 
@@ -351,7 +351,7 @@ public abstract class StaticMacros
                                 : input.toLowerCase();
 
                     default:
-                        throw new MacroParseException( "unimplemented casetype '" + this.toString() + "' for Case macro" );
+                        throw new MacroParseException( "unimplemented casetype '" + this + "' for Case macro" );
                 }
             }
 

+ 4 - 7
server/src/main/java/password/pwm/util/operations/ActionExecutor.java

@@ -274,7 +274,7 @@ public class ActionExecutor
                 : attrValue;
 
 
-        LOGGER.trace( sessionLabel, () -> "beginning ldap " + effectiveLdapMethod.toString() + " operation on " + theUser.getEntryDN() + ", attribute " + attrName );
+        LOGGER.trace( sessionLabel, () -> "beginning ldap " + effectiveLdapMethod + " operation on " + theUser.getEntryDN() + ", attribute " + attrName );
         switch ( effectiveLdapMethod )
         {
             case replace:
@@ -288,8 +288,7 @@ public class ActionExecutor
                 {
                     final String errorMsg = "error setting '" + attrName + "' attribute on user " + theUser.getEntryDN() + ", error: " + e.getMessage();
                     final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_INTERNAL, errorMsg );
-                    final PwmOperationalException newException = new PwmOperationalException( errorInformation );
-                    newException.initCause( e );
+                    final PwmOperationalException newException = new PwmOperationalException( errorInformation, e );
                     throw newException;
                 }
             }
@@ -306,8 +305,7 @@ public class ActionExecutor
                 {
                     final String errorMsg = "error adding '" + attrName + "' attribute value from user " + theUser.getEntryDN() + ", error: " + e.getMessage();
                     final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_INTERNAL, errorMsg );
-                    final PwmOperationalException newException = new PwmOperationalException( errorInformation );
-                    newException.initCause( e );
+                    final PwmOperationalException newException = new PwmOperationalException( errorInformation, e );
                     throw newException;
                 }
 
@@ -325,8 +323,7 @@ public class ActionExecutor
                 {
                     final String errorMsg = "error deleting '" + attrName + "' attribute value on user " + theUser.getEntryDN() + ", error: " + e.getMessage();
                     final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_INTERNAL, errorMsg );
-                    final PwmOperationalException newException = new PwmOperationalException( errorInformation );
-                    newException.initCause( e );
+                    final PwmOperationalException newException = new PwmOperationalException( errorInformation, e );
                     throw newException;
                 }
             }

+ 2 - 2
server/src/main/java/password/pwm/util/password/PasswordRuleChecks.java

@@ -652,7 +652,7 @@ public class PasswordRuleChecks
                     errorList.add( new ErrorInformation( PwmError.PASSWORD_INVALID_CHAR ) );
                     if ( EXTRA_LOGGING )
                     {
-                        LOGGER.trace( () -> "password rejected, does not match configured regex pattern: " + pattern.toString() );
+                        LOGGER.trace( () -> "password rejected, does not match configured regex pattern: " + pattern );
                     }
                 }
             }
@@ -665,7 +665,7 @@ public class PasswordRuleChecks
                     errorList.add( new ErrorInformation( PwmError.PASSWORD_INVALID_CHAR ) );
                     if ( EXTRA_LOGGING )
                     {
-                        LOGGER.trace( () -> "password rejected, matches configured no-regex pattern: " + pattern.toString() );
+                        LOGGER.trace( () -> "password rejected, matches configured no-regex pattern: " + pattern );
                     }
                 }
             }

+ 1 - 1
server/src/main/java/password/pwm/util/password/PasswordRuleReaderHelper.java

@@ -70,7 +70,7 @@ public class PasswordRuleReaderHelper
         else
         {
             // Strip off any thresholds from attribute (specified as: "attributeName:N", where N is a numeric value).
-            final List<String> strippedDisallowedAttributes = new ArrayList<String>();
+            final List<String> strippedDisallowedAttributes = new ArrayList<>();
 
             if ( disallowedAttributes != null )
             {

+ 1 - 1
server/src/main/java/password/pwm/util/password/PasswordUtility.java

@@ -458,7 +458,7 @@ public class PasswordUtility
         }
         catch ( final ChaiPasswordPolicyException e )
         {
-            final String errorMsg = "error setting password for user '" + userIdentity.toDisplayString() + "'' " + e.toString();
+            final String errorMsg = "error setting password for user '" + userIdentity.toDisplayString() + "'' " + e;
             final Optional<PwmError> pwmError = PwmError.forChaiError( e.getErrorCode() );
             final ErrorInformation error = new ErrorInformation( pwmError.orElse( PwmError.PASSWORD_UNKNOWN_VALIDATION ), errorMsg );
             throw new PwmOperationalException( error );

+ 3 - 3
server/src/main/java/password/pwm/util/password/PwmPasswordRuleValidator.java

@@ -133,12 +133,12 @@ public class PwmPasswordRuleValidator
             }
             catch ( final UnsupportedOperationException e )
             {
-                LOGGER.trace( () -> "Unsupported operation was thrown while validating password: " + e.toString() );
+                LOGGER.trace( () -> "Unsupported operation was thrown while validating password: " + e );
             }
             catch ( final ChaiUnavailableException e )
             {
                 StatisticsClient.incrementStat( pwmDomain.getPwmApplication(), Statistic.LDAP_UNAVAILABLE_COUNT );
-                LOGGER.warn( () -> "ChaiUnavailableException was thrown while validating password: " + e.toString() );
+                LOGGER.warn( () -> "ChaiUnavailableException was thrown while validating password: " + e );
                 throw e;
             }
             catch ( final ChaiPasswordPolicyException e )
@@ -146,7 +146,7 @@ public class PwmPasswordRuleValidator
                 final ChaiError passwordError = e.getErrorCode();
                 final PwmError pwmError = PwmError.forChaiError( passwordError ).orElse( PwmError.PASSWORD_UNKNOWN_VALIDATION );
                 final ErrorInformation info = new ErrorInformation( pwmError );
-                LOGGER.trace( () -> "ChaiPasswordPolicyException was thrown while validating password: " + e.toString() );
+                LOGGER.trace( () -> "ChaiPasswordPolicyException was thrown while validating password: " + e );
                 errorResults.add( info );
             }
         }

+ 1 - 1
server/src/main/java/password/pwm/util/secure/PwmTrustManager.java

@@ -156,7 +156,7 @@ public class PwmTrustManager implements X509TrustManager
         if ( !passed )
         {
             final String errorMsg = "server certificate " + X509Utils.makeDebugText( testCertificate )
-                    + " is not signed by configured ROOT CA certificate(s): " + errorText.toString();
+                    + " is not signed by configured ROOT CA certificate(s): " + errorText;
             throw PwmUnrecoverableException.newException( PwmError.ERROR_CERTIFICATE_ERROR, errorMsg );
         }
     }

+ 1 - 1
server/src/main/java/password/pwm/util/secure/SecureEngine.java

@@ -238,7 +238,7 @@ public class SecureEngine
                 workingValue = Arrays.copyOfRange( workingValue, 1, workingValue.length );
                 if ( workingValue.length <= nonceLength )
                 {
-                    throw new PwmUnrecoverableException( new ErrorInformation( PwmError.ERROR_CRYPT_ERROR, "incoming " + blockAlgorithm.toString() + " data is missing nonce" ) );
+                    throw new PwmUnrecoverableException( new ErrorInformation( PwmError.ERROR_CRYPT_ERROR, "incoming " + blockAlgorithm + " data is missing nonce" ) );
                 }
                 final byte[] nonce = Arrays.copyOfRange( workingValue, 0, nonceLength );
                 workingValue = Arrays.copyOfRange( workingValue, nonceLength, workingValue.length );

+ 1 - 1
server/src/main/java/password/pwm/ws/server/rest/RestCheckPasswordServer.java

@@ -219,7 +219,7 @@ public class RestCheckPasswordServer extends RestServlet
         {
             final String errorMessage = "unexpected error executing web service: " + e.getMessage();
             final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_INTERNAL, errorMessage );
-            LOGGER.error( restRequest.getSessionLabel(), () -> errorInformation.toDebugStr(), e );
+            LOGGER.error( restRequest.getSessionLabel(), errorInformation::toDebugStr, e );
             return RestResultBean.fromError( restRequest, errorInformation );
         }
     }

+ 1 - 1
server/src/main/resources/password/pwm/config/PwmSetting.xml

@@ -1611,7 +1611,7 @@
         <default/>
         <regex>^[a-zA-Z0-9.-]{1,1024}=.{1,1024}$</regex>
     </setting>
-    <setting hidden="false" key="network.ip.permittedRange" level="2" required="false">
+    <setting hidden="true" key="network.ip.permittedRange" level="2" required="false">
         <default>
             <value/>
         </default>

+ 1 - 1
server/src/main/resources/password/pwm/i18n/PwmSetting.properties

@@ -527,7 +527,7 @@ Setting_Description_ldap.wireTrace.enable=Enable this option to have @PwmAppName
 Setting_Description_locale.cookie.age=Specify the duration of time to remember a user's locale preferences.  Anytime @PwmAppName@ overrides a browser's default locale setting, it stores a cookie in the browser remembering that setting for the duration of this setting.
 Setting_Description_logoutAfterPasswordChange=Enable this option to force users to log out (and send them to the logoutURL) after a password change.<br/><br/>In most cases, leave this option enabled (default), especially if you are using some type of single sign-on service.
 Setting_Description_network.allowMultiIPSession=Enable this option to allow @PwmAppName@ to access a single HTTP session from different source IP addresses.  Some load balancing or proxy network infrastructures might require this, but in most cases disable it.  Especially since typical sessions are very short, there is not a practical reason for a user to access the same session from multiple client addresses.
-Setting_Description_network.ip.permittedRange=Enable this option to have @PwmAppName@ only permit connections originating from the specified IP address ranges.  If disabled (default), @PwmAppName@ permits any source IP address. <p>Supported range specifications are\:<p><ul><li>Full IPv4 address, such as <b>12.34.56.78</b></li><li>Full IPv6 address, such as <b>2001\:18e8\:3\:171\:218\:8bff\:fe2a\:56a4</b></li><li>Partial IPv4 address, such as <b>12.34</b> (which matches any IP addres starting <b>12.34</b></li><li>IPv4 network/netmask, such as <b>18.25.0.0/255.255.0.0</b></li><li>IPv4 or IPv6 CIDR slash notation, such as <b>18.25.0.0/16</b> or <b>2001\:18e8\:3\:171\:\:/64</b></li></ul>
+Setting_Description_network.ip.permittedRange=DEPRECATED.  Enable this option to have @PwmAppName@ only permit connections originating from the specified IP address ranges.  If disabled (default), @PwmAppName@ permits any source IP address. <p>Supported range specifications are\:<p><ul><li>Full IPv4 address, such as <b>12.34.56.78</b></li><li>Full IPv6 address, such as <b>2001\:18e8\:3\:171\:218\:8bff\:fe2a\:56a4</b></li><li>Partial IPv4 address, such as <b>12.34</b> (which matches any IP addres starting <b>12.34</b></li><li>IPv4 network/netmask, such as <b>18.25.0.0/255.255.0.0</b></li><li>IPv4 or IPv6 CIDR slash notation, such as <b>18.25.0.0/16</b> or <b>2001\:18e8\:3\:171\:\:/64</b></li></ul>
 Setting_Description_network.requiredHttpHeaders=<p>If specified, any HTTP/S request sent to this @PwmAppName@ application server must include these headers.  This feature is useful if you have an upstream security gateway, proxy or web server and wish to only allow sessions from the gateway, and deny direct access to this @PwmAppName@ application server from clients.</p><p>The settings must be in <code>name\=value</code> format.  If the upstream security gateway, proxy or web server is not setting these name/value headers, you will no longer be able to access this @PwmAppName@ application server.</p><p><b>WARNING:</b>If the client you are using to access this server is not setting the headers configured here, this @PwmAppName@ server will become inaccessible.</p>
 Setting_Description_network.reverseDNS.enable=Enable this option to have @PwmAppName@ use its reverse DNS system to record the hostname of the client.  In some cases this can cause performance issues so you can disable it if you do not requrie it.
 Setting_Description_newUser.createContext=Specify the LDAP context where you would like @PwmAppName@ to create new users. You can use macros in this setting.

+ 1 - 1
webapp/src/main/webapp/WEB-INF/jsp/forgottenpassword-method.jsp

@@ -33,7 +33,7 @@
 <%@ taglib uri="pwm" prefix="pwm" %>
 <%
     final PwmRequest pwmRequest = PwmRequest.forRequest(request, response);
-    final Set<IdentityVerificationMethod> methods = new LinkedHashSet<IdentityVerificationMethod>((Set<IdentityVerificationMethod>) JspUtility.getAttribute(pageContext, PwmRequestAttribute.AvailableAuthMethods));
+    final Set<IdentityVerificationMethod> methods = new LinkedHashSet<>( ( Set<IdentityVerificationMethod> ) JspUtility.getAttribute( pageContext, PwmRequestAttribute.AvailableAuthMethods ) );
 %>
 <html lang="<pwm:value name="<%=PwmValue.localeCode%>"/>" dir="<pwm:value name="<%=PwmValue.localeDir%>"/>">
 <%@ include file="fragment/header.jsp" %>

+ 1 - 1
webapp/src/main/webapp/WEB-INF/jsp/fragment/ldap-permissions.jsp

@@ -69,7 +69,7 @@
         </td>
         <td style="text-align: left">
             <%
-                final Set<String> menuLocations = new TreeSet<String>();
+                final Set<String> menuLocations = new TreeSet<>();
                 for (final LDAPPermissionCalculator.PermissionRecord record : entry.getValue().get(access)) {
                     if (record.getPwmSetting() != null) {
                         menuLocations.add(record.getPwmSetting().toMenuLocationDebug(record.getProfile(), JspUtility.locale(request)));

+ 1 - 1
webapp/src/main/webapp/WEB-INF/jsp/fragment/setupresponses-form.jsp

@@ -68,7 +68,7 @@
 <%---------------------- display fields for pwmRandom challenges using SIMPLE mode ----------------------------------------%>
 <% if (setupData.isSimpleMode()) {  %>
 <% // need to output all the random options for the javascript functions.
-    final List<String> questionTexts = new ArrayList<String>();
+    final List<String> questionTexts = new ArrayList<>();
     for (final String indexKey : setupData.getIndexedChallenges().keySet()) {
         final Challenge challenge = setupData.getIndexedChallenges().get(indexKey);
         if (!challenge.isRequired()) {

部分文件因为文件数量过多而无法显示