浏览代码

remove ServletHelper static class

Jason Rivard 9 年之前
父节点
当前提交
db4710f63b
共有 31 个文件被更改,包括 697 次插入751 次删除
  1. 1 0
      src/main/java/password/pwm/AppProperty.java
  2. 127 0
      src/main/java/password/pwm/PwmAboutProperty.java
  3. 1 1
      src/main/java/password/pwm/PwmApplication.java
  4. 1 0
      src/main/java/password/pwm/PwmConstants.java
  5. 1 0
      src/main/java/password/pwm/PwmEnvironment.java
  6. 63 16
      src/main/java/password/pwm/http/PwmRequest.java
  7. 49 0
      src/main/java/password/pwm/http/PwmURL.java
  8. 0 517
      src/main/java/password/pwm/http/ServletHelper.java
  9. 1 5
      src/main/java/password/pwm/http/filter/ConfigAccessFilter.java
  10. 355 7
      src/main/java/password/pwm/http/filter/RequestInitializationFilter.java
  11. 1 17
      src/main/java/password/pwm/http/filter/SessionFilter.java
  12. 1 2
      src/main/java/password/pwm/http/servlet/CaptchaServlet.java
  13. 1 2
      src/main/java/password/pwm/http/servlet/LoginServlet.java
  14. 3 6
      src/main/java/password/pwm/http/servlet/LogoutServlet.java
  15. 2 2
      src/main/java/password/pwm/http/servlet/configguide/ConfigGuideServlet.java
  16. 1 3
      src/main/java/password/pwm/http/servlet/configmanager/ConfigManagerLocalDBServlet.java
  17. 1 1
      src/main/java/password/pwm/http/servlet/configmanager/ConfigManagerServlet.java
  18. 1 2
      src/main/java/password/pwm/http/servlet/configmanager/ConfigManagerWordlistServlet.java
  19. 1 1
      src/main/java/password/pwm/http/servlet/configmanager/DebugItemGenerator.java
  20. 13 13
      src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskServlet.java
  21. 1 1
      src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskVerificationRequestBean.java
  22. 21 0
      src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskVerificationResponseBean.java
  23. 43 0
      src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskVerificationStateBean.java
  24. 3 3
      src/main/java/password/pwm/http/servlet/oauth/OAuthConsumerServlet.java
  25. 0 5
      src/main/java/password/pwm/http/servlet/resource/ResourceFileServlet.java
  26. 0 4
      src/main/java/password/pwm/svc/wordlist/AbstractWordlist.java
  27. 0 133
      src/main/java/password/pwm/util/Helper.java
  28. 2 1
      src/main/java/password/pwm/util/X509Utils.java
  29. 2 2
      src/main/java/password/pwm/ws/client/rest/naaf/NAAFEndPoint.java
  30. 0 7
      src/main/java/password/pwm/ws/server/RestServerHelper.java
  31. 1 0
      src/main/resources/password/pwm/AppProperty.properties

+ 1 - 0
src/main/java/password/pwm/AppProperty.java

@@ -86,6 +86,7 @@ public enum AppProperty {
     HTTP_BODY_MAXREAD_LENGTH                        ("http.body.maxReadLength"),
     HTTP_ENABLE_GZIP                                ("http.gzip.enable"),
     HTTP_ERRORS_ALLOW_HTML                          ("http.errors.allowHtml"),
+    HTTP_HEADER_SERVER                              ("http.header.server"),
     HTTP_HEADER_SEND_XAMB                           ("http.header.sendXAmb"),
     HTTP_HEADER_SEND_XINSTANCE                      ("http.header.sendXInstance"),
     HTTP_HEADER_SEND_XNOISE                         ("http.header.sendXNoise"),

+ 127 - 0
src/main/java/password/pwm/PwmAboutProperty.java

@@ -22,6 +22,20 @@
 
 package password.pwm;
 
+import password.pwm.config.PwmSetting;
+import password.pwm.i18n.Display;
+import password.pwm.util.FileSystemUtility;
+import password.pwm.util.Helper;
+import password.pwm.util.LocaleHelper;
+import password.pwm.util.db.DatabaseAccessor;
+import password.pwm.util.logging.PwmLogger;
+import password.pwm.util.secure.PwmRandom;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.Map;
+import java.util.TreeMap;
+
 public enum PwmAboutProperty {
 
     app_version,
@@ -76,4 +90,117 @@ public enum PwmAboutProperty {
     database_driverVersion,
     database_databaseProductName,
     database_databaseProductVersion,
+
+    ;
+
+    private static final PwmLogger LOGGER = PwmLogger.forClass(PwmAboutProperty.class);
+
+    public static Map<PwmAboutProperty,String> makeInfoBean(
+            final PwmApplication pwmApplication
+    ) {
+        final Map<PwmAboutProperty,String> aboutMap = new TreeMap<>();
+
+        // about page
+        aboutMap.put(app_version,                  PwmConstants.SERVLET_VERSION);
+        aboutMap.put(app_currentTime,              dateFormatForInfoBean(new Date()));
+        aboutMap.put(app_startTime,                dateFormatForInfoBean(pwmApplication.getStartupTime()));
+        aboutMap.put(app_installTime,              dateFormatForInfoBean(pwmApplication.getInstallTime()));
+        aboutMap.put(app_siteUrl,                  pwmApplication.getConfig().readSettingAsString(PwmSetting.PWM_SITE_URL));
+        aboutMap.put(app_instanceID,               pwmApplication.getInstanceID());
+        aboutMap.put(app_chaiApiVersion,           PwmConstants.CHAI_API_VERSION);
+
+        if (pwmApplication.getConfig().readSettingAsBoolean(PwmSetting.VERSION_CHECK_ENABLE)) {
+            if (pwmApplication.getVersionChecker() != null) {
+                aboutMap.put(app_currentPublishedVersion, pwmApplication.getVersionChecker().currentVersion());
+                aboutMap.put(app_currentPublishedVersionCheckTime, dateFormatForInfoBean(pwmApplication.getVersionChecker().lastReadTimestamp()));
+            }
+        }
+
+        aboutMap.put(app_secureBlockAlgorithm,     pwmApplication.getSecureService().getDefaultBlockAlgorithm().getLabel());
+        aboutMap.put(app_secureHashAlgorithm,      pwmApplication.getSecureService().getDefaultHashAlgorithm().toString());
+
+        aboutMap.put(app_wordlistSize,             Integer.toString(pwmApplication.getWordlistManager().size()));
+        aboutMap.put(app_seedlistSize,             Integer.toString(pwmApplication.getSeedlistManager().size()));
+        if (pwmApplication.getSharedHistoryManager() != null) {
+            aboutMap.put(app_sharedHistorySize,    Integer.toString(pwmApplication.getSharedHistoryManager().size()));
+            aboutMap.put(app_sharedHistoryOldestTime, dateFormatForInfoBean(pwmApplication.getSharedHistoryManager().getOldestEntryTime()));
+        }
+
+
+        if (pwmApplication.getEmailQueue() != null) {
+            aboutMap.put(app_emailQueueSize,       Integer.toString(pwmApplication.getEmailQueue().queueSize()));
+            aboutMap.put(app_emailQueueOldestTime, dateFormatForInfoBean(pwmApplication.getEmailQueue().eldestItem()));
+        }
+
+        if (pwmApplication.getSmsQueue() != null) {
+            aboutMap.put(app_smsQueueSize,         Integer.toString(pwmApplication.getSmsQueue().queueSize()));
+            aboutMap.put(app_smsQueueOldestTime,   dateFormatForInfoBean(pwmApplication.getSmsQueue().eldestItem()));
+        }
+
+        if (pwmApplication.getAuditManager() != null) {
+            aboutMap.put(app_syslogQueueSize,      Integer.toString(pwmApplication.getAuditManager().syslogQueueSize()));
+        }
+
+        if (pwmApplication.getLocalDB() != null) {
+            aboutMap.put(app_localDbLogSize,       Integer.toString(pwmApplication.getLocalDBLogger().getStoredEventCount()));
+            aboutMap.put(app_localDbLogOldestTime, dateFormatForInfoBean(pwmApplication.getLocalDBLogger().getTailDate()));
+
+            aboutMap.put(app_localDbStorageSize,   Helper.formatDiskSize(FileSystemUtility.getFileDirectorySize(pwmApplication.getLocalDB().getFileLocation())));
+            aboutMap.put(app_localDbFreeSpace,     Helper.formatDiskSize(FileSystemUtility.diskSpaceRemaining(pwmApplication.getLocalDB().getFileLocation())));
+        }
+
+
+        { // java info
+            final Runtime runtime = Runtime.getRuntime();
+            aboutMap.put(java_memoryFree,          Long.toString(runtime.freeMemory()));
+            aboutMap.put(java_memoryAllocated,     Long.toString(runtime.totalMemory()));
+            aboutMap.put(java_memoryMax,           Long.toString(runtime.maxMemory()));
+            aboutMap.put(java_threadCount,         Integer.toString(Thread.activeCount()));
+
+            aboutMap.put(java_vmVendor,            System.getProperty("java.vm.vendor"));
+
+            aboutMap.put(java_runtimeVersion,      System.getProperty("java.runtime.version"));
+            aboutMap.put(java_vmVersion,           System.getProperty("java.vm.version"));
+            aboutMap.put(java_vmName,              System.getProperty("java.vm.name"));
+            aboutMap.put(java_vmLocation,          System.getProperty("java.home"));
+
+            aboutMap.put(java_osName,              System.getProperty("os.name"));
+            aboutMap.put(java_osVersion,           System.getProperty("os.version"));
+            aboutMap.put(java_randomAlgorithm,     PwmRandom.getInstance().getAlgorithm());
+        }
+
+        { // build info
+            aboutMap.put(build_Time,               PwmConstants.BUILD_TIME);
+            aboutMap.put(build_Number,             PwmConstants.BUILD_NUMBER);
+            aboutMap.put(build_Type,               PwmConstants.BUILD_TYPE);
+            aboutMap.put(build_User,               PwmConstants.BUILD_USER);
+            aboutMap.put(build_Revision,           PwmConstants.BUILD_REVISION);
+            aboutMap.put(build_JavaVendor,         PwmConstants.BUILD_JAVA_VENDOR);
+            aboutMap.put(build_JavaVersion,        PwmConstants.BUILD_JAVA_VERSION);
+            aboutMap.put(build_Version,            PwmConstants.BUILD_VERSION);
+        }
+
+        { // database info
+            try {
+                final DatabaseAccessor databaseAccessor = pwmApplication.getDatabaseAccessor();
+                if (databaseAccessor != null) {
+                    final Map<PwmAboutProperty,String> debugData = databaseAccessor.getConnectionDebugProperties();
+                    aboutMap.putAll(debugData);
+                }
+            } catch (Throwable t) {
+                LOGGER.error("error reading database debug properties");
+            }
+        }
+
+        return Collections.unmodifiableMap(aboutMap);
+    }
+
+    private static String dateFormatForInfoBean(final Date date) {
+        if (date != null) {
+            return PwmConstants.DEFAULT_DATETIME_FORMAT.format(date);
+        } else {
+            return LocaleHelper.getLocalizedMessage(PwmConstants.DEFAULT_LOCALE, Display.Value_NotApplicable, null);
+        }
+
+    }
 }

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

@@ -290,7 +290,7 @@ public class PwmApplication {
         }
 
         try {
-            Map<PwmAboutProperty,String> infoMap = Helper.makeInfoBean(this);
+            Map<PwmAboutProperty,String> infoMap = PwmAboutProperty.makeInfoBean(this);
             LOGGER.trace("application info: " + JsonUtil.serializeMap(infoMap));
         } catch (Exception e) {
             LOGGER.error("error generating about application bean: " + e.getMessage());

+ 1 - 0
src/main/java/password/pwm/PwmConstants.java

@@ -254,6 +254,7 @@ public abstract class PwmConstants {
     public static final String PARAM_LDAP_PROFILE = "ldapProfile";
     public static final String PARAM_SKIP_CAPTCHA = "skipCaptcha";
     public static final String PARAM_POST_LOGIN_URL = "posturl";
+    public static final String PARAM_FILE_UPLOAD = "fileUpload";
 
     public static final String COOKIE_PERSISTENT_CONFIG_LOGIN = "persistentConfigLogin";
 

+ 1 - 0
src/main/java/password/pwm/PwmEnvironment.java

@@ -57,6 +57,7 @@ public class PwmEnvironment implements Serializable {
 
     public enum ApplicationFlag {
         Appliance,
+        Docker,
         ManageHttps,
         NoFileLock,
         CommandLineInstance,

+ 63 - 16
src/main/java/password/pwm/http/PwmRequest.java

@@ -25,6 +25,7 @@ package password.pwm.http;
 import org.apache.commons.fileupload.FileItemIterator;
 import org.apache.commons.fileupload.FileItemStream;
 import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.commons.io.IOUtils;
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
 import password.pwm.Validator;
@@ -170,7 +171,7 @@ public class PwmRequest extends PwmHttpRequestWrapper implements Serializable {
             throws PwmUnrecoverableException, IOException
     {
         String redirectURL = this.getContextPath() + PwmServletDefinition.Command.servletUrl();
-        redirectURL = ServletHelper.appendAndEncodeUrlParameters(redirectURL,Collections.singletonMap(PwmConstants.PARAM_ACTION_REQUEST,"continue"));
+        redirectURL = PwmURL.appendAndEncodeUrlParameters(redirectURL, Collections.singletonMap(PwmConstants.PARAM_ACTION_REQUEST, "continue"));
         sendRedirect(redirectURL);
     }
 
@@ -187,6 +188,30 @@ public class PwmRequest extends PwmHttpRequestWrapper implements Serializable {
         return ContextManager.getContextManager(this);
     }
 
+    public InputStream readFileUploadStream(final String filePartName)
+            throws IOException, ServletException, PwmUnrecoverableException
+    {
+        try {
+            if (ServletFileUpload.isMultipartContent(this.getHttpServletRequest())) {
+
+                // Create a new file upload handler
+                final ServletFileUpload upload = new ServletFileUpload();
+
+                // Parse the request
+                for (final FileItemIterator iter = upload.getItemIterator(this.getHttpServletRequest()); iter.hasNext();) {
+                    final FileItemStream item = iter.next();
+
+                    if (filePartName.equals(item.getFieldName())) {
+                        return item.openStream();
+                    }
+                }
+            }
+        } catch (Exception e) {
+            LOGGER.error("error reading file upload: " + e.getMessage());
+        }
+        return null;
+    }
+
     public Map<String,FileUploadItem> readFileUploads(
             final int maxFileSize,
             final int maxItems
@@ -196,26 +221,18 @@ public class PwmRequest extends PwmHttpRequestWrapper implements Serializable {
         final Map<String,FileUploadItem> returnObj = new LinkedHashMap<>();
         try {
             if (ServletFileUpload.isMultipartContent(this.getHttpServletRequest())) {
-                final byte[] buffer = new byte[1024 * 4];
-
                 final ServletFileUpload upload = new ServletFileUpload();
                 final FileItemIterator iter = upload.getItemIterator(this.getHttpServletRequest());
                 while (iter.hasNext() && returnObj.size() < maxItems) {
                     final FileItemStream item = iter.next();
                     final InputStream inputStream = item.openStream();
                     final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                    int length;
-                    while ((length = inputStream.read(buffer)) > 0) {
-                        baos.write(buffer, 0, length);
-                        if (baos.size() > maxFileSize) {
-                            while ((inputStream.read(buffer)) > 0) {
-                                // read & ignore file.
-                            }
-                            final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNKNOWN,"upload file size limit exceeded");
-                            LOGGER.error(this, errorInformation);
-                            respondWithError(errorInformation);
-                            return Collections.emptyMap();
-                        }
+                    final long length = IOUtils.copyLarge(inputStream, baos, 0, maxFileSize + 1);
+                    if (length > maxFileSize) {
+                        final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNKNOWN,"upload file size limit exceeded");
+                        LOGGER.error(this, errorInformation);
+                        respondWithError(errorInformation);
+                        return Collections.emptyMap();
                     }
                     final byte[] outputFile = baos.toByteArray();
                     final FileUploadItem fileUploadItem = new FileUploadItem(
@@ -573,11 +590,41 @@ public class PwmRequest extends PwmHttpRequestWrapper implements Serializable {
 
     public String getURLwithQueryString() throws PwmUnrecoverableException {
         final HttpServletRequest req = this.getHttpServletRequest();
-        return ServletHelper.appendAndEncodeUrlParameters(req.getRequestURI(), readParametersAsMap());
+        return PwmURL.appendAndEncodeUrlParameters(req.getRequestURI(), readParametersAsMap());
     }
 
     public String getURLwithoutQueryString() throws PwmUnrecoverableException {
         final HttpServletRequest req = this.getHttpServletRequest();
         return req.getRequestURI();
     }
+
+    public String debugHttpHeaders() {
+        final String LINE_SEPERATOR = "\n";
+        final StringBuilder sb = new StringBuilder();
+
+
+        sb.append("http").append(getHttpServletRequest().isSecure() ? "s " : " non-").append("secure request headers: ");
+        sb.append(LINE_SEPERATOR);
+
+        final Map<String,List<String>> headerMap = readHeaderValuesMap();
+        for (final String headerName : headerMap.keySet()) {
+            for (final String value : headerMap.get(headerName)) {
+                sb.append("  ");
+                sb.append(headerName);
+                sb.append("=");
+                if (headerName.contains("Authorization")) {
+                    sb.append(PwmConstants.LOG_REMOVED_VALUE_REPLACEMENT);
+                } else {
+                    sb.append(value);
+                }
+                sb.append(LINE_SEPERATOR);
+            }
+        }
+
+        if (LINE_SEPERATOR.equals(sb.substring(sb.length() - LINE_SEPERATOR.length(), sb.length()))) {
+            sb.delete(sb.length() - LINE_SEPERATOR.length(), sb.length());
+        }
+
+        return sb.toString();
+    }
 }

+ 49 - 0
src/main/java/password/pwm/http/PwmURL.java

@@ -24,6 +24,7 @@ package password.pwm.http;
 
 import password.pwm.PwmConstants;
 import password.pwm.http.servlet.PwmServletDefinition;
+import password.pwm.util.StringUtil;
 
 import javax.servlet.http.HttpServletRequest;
 import java.net.URI;
@@ -181,4 +182,52 @@ public class PwmURL {
         }
         return urlSegments;
     }
+
+    public static String appendAndEncodeUrlParameters(
+            final String inputUrl,
+            final Map<String, String> parameters
+    )
+    {
+        final StringBuilder output = new StringBuilder();
+        output.append(inputUrl == null ? "" : inputUrl);
+
+        if (parameters != null) {
+            for (final String key : parameters.keySet()) {
+                final String value = parameters.get(key);
+                final String encodedValue = StringUtil.urlEncode(value);
+
+                output.append(output.toString().contains("?") ? "&" : "?");
+                output.append(key);
+                output.append("=");
+                output.append(encodedValue);
+            }
+        }
+
+        if (output.charAt(0) == '?' || output.charAt(0) == '&') {
+            output.deleteCharAt(0);
+        }
+
+        return output.toString();
+    }
+
+    public static int portForUriSchema(final URI uri) {
+        final int port = uri.getPort();
+        if (port < 1) {
+            return portForUriScheme(uri.getScheme());
+        }
+        return port;
+    }
+
+    private static int portForUriScheme(final String scheme) {
+        if (scheme == null) {
+            throw new NullPointerException("scheme cannot be null");
+        }
+        switch (scheme) {
+            case "http": return 80;
+            case "https": return 443;
+            case "ldap": return 389;
+            case "ldaps": return 636;
+        }
+        throw new IllegalArgumentException("unknown scheme: " + scheme);
+    }
 }

+ 0 - 517
src/main/java/password/pwm/http/ServletHelper.java

@@ -1,517 +0,0 @@
-/*
- * Password Management Servlets (PWM)
- * http://code.google.com/p/pwm/
- *
- * Copyright (c) 2006-2009 Novell, Inc.
- * Copyright (c) 2009-2015 The PWM Project
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-package password.pwm.http;
-
-import org.apache.commons.fileupload.FileItemIterator;
-import org.apache.commons.fileupload.FileItemStream;
-import org.apache.commons.fileupload.servlet.ServletFileUpload;
-import password.pwm.AppProperty;
-import password.pwm.PwmApplication;
-import password.pwm.PwmConstants;
-import password.pwm.Validator;
-import password.pwm.bean.LocalSessionStateBean;
-import password.pwm.config.Configuration;
-import password.pwm.config.PwmSetting;
-import password.pwm.error.ErrorInformation;
-import password.pwm.error.PwmError;
-import password.pwm.error.PwmUnrecoverableException;
-import password.pwm.svc.stats.Statistic;
-import password.pwm.svc.stats.StatisticsManager;
-import password.pwm.util.IPMatcher;
-import password.pwm.util.LocaleHelper;
-import password.pwm.util.StringUtil;
-import password.pwm.util.TimeDuration;
-import password.pwm.util.logging.PwmLogger;
-import password.pwm.util.secure.PwmRandom;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.math.BigInteger;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.*;
-
-public class ServletHelper {
-
-    private static final PwmLogger LOGGER = PwmLogger.forClass(ServletHelper.class);
-
-    public static String debugHttpHeaders(final HttpServletRequest req) {
-        final StringBuilder sb = new StringBuilder();
-
-        sb.append("http").append(req.isSecure() ? "s " : " non-").append("secure request headers: ");
-        sb.append("\n");
-
-        for (Enumeration enumeration = req.getHeaderNames(); enumeration.hasMoreElements();) {
-            final String headerName = (enumeration.nextElement()).toString();
-            sb.append("  ");
-            sb.append(headerName);
-            sb.append("=");
-            if (headerName.contains("Authorization")) {
-                sb.append(PwmConstants.LOG_REMOVED_VALUE_REPLACEMENT);
-            } else {
-                sb.append(req.getHeader(headerName));
-            }
-            sb.append(enumeration.hasMoreElements() ? "\n" : "");
-        }
-
-        return sb.toString();
-    }
-
-
-    public static void addPwmResponseHeaders(
-            final PwmRequest pwmRequest,
-            boolean fromServlet
-    ) {
-
-        if (pwmRequest == null) {
-            return;
-        }
-        final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
-        final PwmSession pwmSession = pwmRequest.getPwmSession();
-        final PwmResponse resp = pwmRequest.getPwmResponse();
-
-        if (!resp.isCommitted()) {
-            final boolean includeXAmb = Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_HEADER_SEND_XAMB));
-            final boolean includeXInstance = Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_HEADER_SEND_XINSTANCE));
-            final boolean includeXSessionID = Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_HEADER_SEND_XSESSIONID));
-            final boolean includeXVersion = Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_HEADER_SEND_XVERSION));
-            final boolean includeXContentTypeOptions = Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_HEADER_SEND_XCONTENTTYPEOPTIONS));
-            final boolean includeXXSSProtection = Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_HEADER_SEND_XXSSPROTECTION));
-
-
-            final boolean includeXFrameDeny = pwmApplication.getConfig().readSettingAsBoolean(PwmSetting.SECURITY_PREVENT_FRAMING);
-            final boolean sendNoise = Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(
-                    AppProperty.HTTP_HEADER_SEND_XNOISE));
-
-            if (sendNoise) {
-                resp.setHeader(
-                        PwmConstants.HttpHeader.XNoise,
-                        PwmRandom.getInstance().alphaNumericString(PwmRandom.getInstance().nextInt(100)+10)
-                );
-            }
-
-            if (fromServlet && includeXAmb) {
-                resp.setHeader(PwmConstants.HttpHeader.XAmb, PwmConstants.X_AMB_HEADER[PwmRandom.getInstance().nextInt(PwmConstants.X_AMB_HEADER.length)]);
-            }
-
-            if (includeXVersion) {
-                resp.setHeader(PwmConstants.HttpHeader.XVersion, PwmConstants.SERVLET_VERSION);
-            }
-
-            if (includeXContentTypeOptions) {
-                resp.setHeader(PwmConstants.HttpHeader.XContentTypeOptions, "nosniff");
-            }
-
-            if (includeXXSSProtection) {
-                resp.setHeader(PwmConstants.HttpHeader.XXSSProtection, "1");
-            }
-
-            if (includeXInstance) {
-                resp.setHeader(PwmConstants.HttpHeader.XInstance, String.valueOf(pwmApplication.getInstanceID()));
-            }
-
-            if (includeXSessionID && pwmSession != null) {
-                resp.setHeader(PwmConstants.HttpHeader.XSessionID, pwmSession.getSessionStateBean().getSessionID());
-            }
-
-            if (includeXFrameDeny && fromServlet) {
-                resp.setHeader(PwmConstants.HttpHeader.XFrameOptions, "DENY");
-            }
-
-
-            if (fromServlet) {
-                resp.setHeader(PwmConstants.HttpHeader.Cache_Control, "no-cache, no-store, must-revalidate, proxy-revalidate");
-            }
-
-            if (fromServlet && pwmSession != null) {
-                final String contentPolicy = pwmApplication.getConfig().readSettingAsString(PwmSetting.SECURITY_CSP_HEADER);
-                if (contentPolicy != null && !contentPolicy.isEmpty()) {
-                    final String nonce = pwmRequest.getCspNonce();
-                    final String expandedPolicy = contentPolicy.replace("%NONCE%", nonce);
-                    resp.setHeader(PwmConstants.HttpHeader.ContentSecurityPolicy, expandedPolicy);
-                }
-            }
-
-            resp.setHeader(PwmConstants.HttpHeader.Server, null);
-        }
-    }
-
-    public static String readCookie(final HttpServletRequest req, final String cookieName) {
-        if (req == null || cookieName == null) {
-            return null;
-        }
-        final Cookie[] cookies = req.getCookies();
-        if (cookies != null) {
-            for (final Cookie cookie : cookies) {
-                if (cookie != null) {
-                    final String loopName = cookie.getName();
-                    if (cookieName.equals(loopName)) {
-                        return StringUtil.urlDecode(cookie.getValue());
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-
-    public static boolean cookieEquals(final HttpServletRequest req, final String cookieName, final String cookieValue) {
-        final String value = readCookie(req, cookieName);
-        if (value == null) {
-            return cookieValue == null;
-        }
-        return value.equals(cookieValue);
-    }
-
-    public static String readUserHostname(final HttpServletRequest req, final PwmSession pwmSession) throws PwmUnrecoverableException {
-        final Configuration config = ContextManager.getPwmApplication(req).getConfig();
-        if (config != null && !config.readSettingAsBoolean(PwmSetting.REVERSE_DNS_ENABLE)) {
-            return "";
-        }
-
-        final String userIPAddress = readUserIPAddress(req, pwmSession);
-        try {
-            return InetAddress.getByName(userIPAddress).getCanonicalHostName();
-        } catch (UnknownHostException e) {
-            LOGGER.trace(pwmSession, "unknown host while trying to compute hostname for src request: " + e.getMessage());
-        }
-        return "";
-    }
-
-    /**
-     * Returns the IP address of the user.  If there is an X-Forwarded-For header in the request, that address will
-     * be used.  Otherwise, the source address of the request is used.
-     *
-     * @param req        A valid HttpServletRequest.
-     * @param pwmSession pwmSession used for config lookup
-     * @return String containing the textual representation of the source IP address, or null if the request is invalid.
-     */
-    public static String readUserIPAddress(final HttpServletRequest req, final PwmSession pwmSession) throws PwmUnrecoverableException {
-        final Configuration config = ContextManager.getPwmApplication(req).getConfig();
-        final boolean useXForwardedFor = config != null && config.readSettingAsBoolean(PwmSetting.USE_X_FORWARDED_FOR_HEADER);
-
-        String userIP = "";
-
-        if (useXForwardedFor) {
-            try {
-                userIP = req.getHeader(PwmConstants.HTTP_HEADER_X_FORWARDED_FOR);
-            } catch (Exception e) {
-                //ip address not in header (no X-Forwarded-For)
-            }
-        }
-
-        if (userIP == null || userIP.length() < 1) {
-            userIP = req.getRemoteAddr();
-        }
-
-        return userIP == null ? "" : userIP;
-    }
-
-
-    public static String readFileUpload(
-            final HttpServletRequest req,
-            final String filePartName,
-            int maxFileChars
-    )
-            throws IOException, ServletException, PwmUnrecoverableException
-    {
-        try {
-            if (ServletFileUpload.isMultipartContent(req)) {
-
-                // Create a new file upload handler
-                final ServletFileUpload upload = new ServletFileUpload();
-
-                String uploadFile = null;
-
-                // Parse the request
-                for (final FileItemIterator iter = upload.getItemIterator(req); iter.hasNext();) {
-                    final FileItemStream item = iter.next();
-
-                    if (filePartName.equals(item.getFieldName())) {
-                        uploadFile = streamToString(item.openStream(),maxFileChars);
-                    }
-                }
-
-                return uploadFile;
-            }
-        } catch (Exception e) {
-            LOGGER.error("error reading file upload: " + e.getMessage());
-        }
-        return null;
-    }
-
-    public static InputStream readFileUpload(
-            final HttpServletRequest req,
-            final String filePartName
-    )
-            throws IOException, ServletException, PwmUnrecoverableException
-    {
-        try {
-            if (ServletFileUpload.isMultipartContent(req)) {
-
-                // Create a new file upload handler
-                final ServletFileUpload upload = new ServletFileUpload();
-
-                // Parse the request
-                for (final FileItemIterator iter = upload.getItemIterator(req); iter.hasNext();) {
-                    final FileItemStream item = iter.next();
-
-                    if (filePartName.equals(item.getFieldName())) {
-                        return item.openStream();
-                    }
-                }
-            }
-        } catch (Exception e) {
-            LOGGER.error("error reading file upload: " + e.getMessage());
-        }
-        return null;
-    }
-
-    private static String streamToString(final InputStream stream, final int maxFileChars)
-            throws IOException, PwmUnrecoverableException {
-        final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream,PwmConstants.DEFAULT_CHARSET));
-        final StringBuilder sb = new StringBuilder();
-        int charCounter = 0;
-        int nextChar = bufferedReader.read();
-        while (nextChar != -1) {
-            charCounter++;
-            sb.append((char)nextChar);
-            nextChar = bufferedReader.read();
-            if (charCounter > maxFileChars) {
-                stream.close();
-                throw new PwmUnrecoverableException(new ErrorInformation(PwmError.CONFIG_UPLOAD_FAILURE,"file too large"));
-            }
-        }
-        return sb.toString();
-    }
-
-    public static void handleRequestInitialization(
-            final PwmRequest pwmRequest,
-            final PwmApplication pwmApplication,
-            final PwmSession pwmSession
-    )
-            throws PwmUnrecoverableException
-    {
-        final LocalSessionStateBean ssBean = pwmSession.getSessionStateBean();
-        final PwmURL pwmURL = pwmRequest.getURL();
-
-        // mark if first request
-        if (ssBean.getSessionCreationTime() == null) {
-            ssBean.setSessionCreationTime(new Date());
-            ssBean.setSessionLastAccessedTime(new Date());
-        }
-
-        // mark session ip address
-        if (ssBean.getSrcAddress() == null) {
-            ssBean.setSrcAddress(readUserIPAddress(pwmRequest.getHttpServletRequest(), pwmSession));
-        }
-
-        // mark the user's hostname in the session bean
-        if (ssBean.getSrcHostname() == null) {
-            ssBean.setSrcHostname(readUserHostname(pwmRequest.getHttpServletRequest(), pwmSession));
-        }
-
-        // update the privateUrlAccessed flag
-        if (pwmURL.isPrivateUrl()) {
-            ssBean.setPrivateUrlAccessed(true);
-        }
-
-        // initialize the session's locale
-        if (ssBean.getLocale() == null) {
-            initializeLocaleAndTheme(pwmRequest, pwmApplication, pwmSession);
-        }
-
-        // set idle timeout (may get overridden by module-specific values elsewhere
-        if (!pwmURL.isResourceURL() && !pwmURL.isCommandServletURL() && !pwmURL.isWebServiceURL()){
-            final int sessionIdleSeconds = (int) pwmApplication.getConfig().readSettingAsLong(PwmSetting.IDLE_TIMEOUT_SECONDS);
-            pwmSession.setSessionTimeout(pwmRequest.getHttpServletRequest().getSession(), sessionIdleSeconds);
-        }
-    }
-
-    private static void initializeLocaleAndTheme(
-            final PwmRequest pwmRequest,
-            final PwmApplication pwmApplication,
-            final PwmSession pwmSession
-    )
-            throws PwmUnrecoverableException
-    {
-        final String localeCookieName = pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_COOKIE_LOCALE_NAME);
-        final String localeCookie = ServletHelper.readCookie(pwmRequest.getHttpServletRequest(), localeCookieName);
-        if (localeCookieName.length() > 0 && localeCookie != null) {
-            LOGGER.debug(pwmSession, "detected locale cookie in request, setting locale to " + localeCookie);
-            pwmSession.setLocale(pwmApplication, localeCookie);
-        } else {
-            final List<Locale> knownLocales = pwmApplication.getConfig().getKnownLocales();
-            final Locale userLocale = LocaleHelper.localeResolver(pwmRequest.getLocale(), knownLocales);
-            pwmSession.getSessionStateBean().setLocale(userLocale == null ? PwmConstants.DEFAULT_LOCALE : userLocale);
-            LOGGER.trace(pwmSession, "user locale set to '" + pwmSession.getSessionStateBean().getLocale() + "'");
-        }
-
-        final String themeCookieName = pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_COOKIE_THEME_NAME);
-        final String themeCookie = ServletHelper.readCookie(pwmRequest.getHttpServletRequest(), themeCookieName);
-        if (localeCookieName.length() > 0 && themeCookie != null && themeCookie.length() > 0) {
-            if (pwmApplication.getResourceServletService().checkIfThemeExists(pwmRequest, themeCookie)) {
-                LOGGER.debug(pwmSession, "detected theme cookie in request, setting theme to " + themeCookie);
-                pwmSession.getSessionStateBean().setTheme(themeCookie);
-            }
-        }
-    }
-
-    public static void handleRequestSecurityChecks(
-            final HttpServletRequest req,
-            final PwmApplication pwmApplication,
-            final PwmSession pwmSession
-    )
-            throws PwmUnrecoverableException
-    {
-        final LocalSessionStateBean ssBean = pwmSession.getSessionStateBean();
-
-        // check the user's IP address
-        if (!pwmApplication.getConfig().readSettingAsBoolean(PwmSetting.MULTI_IP_SESSION_ALLOWED)) {
-            final String remoteAddress = readUserIPAddress(req, pwmSession);
-            if (!ssBean.getSrcAddress().equals(remoteAddress)) {
-                final String errorMsg = "current network address '" + remoteAddress + "' has changed from original network address '" + ssBean.getSrcAddress() + "'";
-                final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION,errorMsg);
-                throw new PwmUnrecoverableException(errorInformation);
-            }
-        }
-
-        // check total time.
-        {
-            if (ssBean.getSessionCreationTime() != null) {
-                final Long maxSessionSeconds = pwmApplication.getConfig().readSettingAsLong(PwmSetting.SESSION_MAX_SECONDS);
-                final TimeDuration sessionAge = TimeDuration.fromCurrent(ssBean.getSessionCreationTime());
-                if (sessionAge.getTotalSeconds() > maxSessionSeconds) {
-                    final String errorMsg = "session age (" + sessionAge.asCompactString() + ") is longer than maximum permitted age";
-                    final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION,errorMsg);
-                    throw new PwmUnrecoverableException(errorInformation);
-                }
-            }
-        }
-
-        // check headers
-        {
-            final List<String> requiredHeaders = pwmApplication.getConfig().readSettingAsStringArray(PwmSetting.REQUIRED_HEADERS);
-            if (requiredHeaders != null && !requiredHeaders.isEmpty()) {
-                final Map<String, String> configuredValues  = StringUtil.convertStringListToNameValuePair(requiredHeaders, "=");
-                for (final String key : configuredValues.keySet()) {
-                    if (key != null && key.length() > 0) {
-                        final String requiredValue = configuredValues.get(key);
-                        if (requiredValue != null && requiredValue.length() > 0) {
-                            final String value = Validator.sanitizeInputValue(pwmApplication.getConfig(),
-                                    req.getHeader(key), 1024);
-                            if (value == null || value.length() < 1) {
-                                final String errorMsg = "request is missing required value for header '" + key + "'";
-                                final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION,errorMsg);
-                                throw new PwmUnrecoverableException(errorInformation);
-                            } else {
-                                if (!requiredValue.equals(value)) {
-                                    final String errorMsg = "request has incorrect required value for header '" + key + "'";
-                                    final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION,errorMsg);
-                                    throw new PwmUnrecoverableException(errorInformation);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        // check permitted source IP address
-        {
-            final List<String> requiredHeaders = pwmApplication.getConfig().readSettingAsStringArray(PwmSetting.IP_PERMITTED_RANGE);
-            if (requiredHeaders != null && !requiredHeaders.isEmpty()) {
-                boolean match = false;
-                final String requestAddress = req.getRemoteAddr();
-                for (int i = 0; i < requiredHeaders.size() && !match; i++) {
-                    String ipMatchString = requiredHeaders.get(i);
-                    try {
-                        final IPMatcher ipMatcher = new IPMatcher(ipMatchString);
-                        try {
-                            if (ipMatcher.match(requestAddress)) {
-                                match = true;
-                            }
-                        } catch (IPMatcher.IPMatcherException e) {
-                            LOGGER.error("error while attempting to match permitted address range '" + ipMatchString + "', error: " + e);
-                        }
-                    } catch (IPMatcher.IPMatcherException e) {
-                        LOGGER.error("error parsing permitted address range '" + ipMatchString + "', error: " + e);
-                    }
-                }
-                if (!match) {
-                    final String errorMsg = "request network address '" + req.getRemoteAddr() + "' does not match any configured permitted source address";
-                    final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION,errorMsg);
-                    throw new PwmUnrecoverableException(errorInformation);
-                }
-            }
-        }
-
-        // check trial
-        if (PwmConstants.TRIAL_MODE) {
-            final String currentAuthString = pwmApplication.getStatisticsManager().getStatBundleForKey(StatisticsManager.KEY_CURRENT).getStatistic(Statistic.AUTHENTICATIONS);
-            if (new BigInteger(currentAuthString).compareTo(BigInteger.valueOf(PwmConstants.TRIAL_MAX_AUTHENTICATIONS)) > 0) {
-                throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_TRIAL_VIOLATION,"maximum usage per server startup exceeded"));
-            }
-
-            final String totalAuthString = pwmApplication.getStatisticsManager().getStatBundleForKey(StatisticsManager.KEY_CUMULATIVE).getStatistic(Statistic.AUTHENTICATIONS);
-            if (new BigInteger(totalAuthString).compareTo(BigInteger.valueOf(PwmConstants.TRIAL_MAX_TOTAL_AUTH)) > 0) {
-                throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_TRIAL_VIOLATION,"maximum usage for this server has been exceeded"));
-            }
-        }
-
-        // check intruder
-        pwmApplication.getIntruderManager().convenience().checkAddressAndSession(pwmSession);
-    }
-
-    public static String appendAndEncodeUrlParameters(
-            final String inputUrl,
-            final Map<String, String> parameters
-    )
-    {
-        final StringBuilder output = new StringBuilder();
-        output.append(inputUrl == null ? "" : inputUrl);
-
-        if (parameters != null) {
-            for (final String key : parameters.keySet()) {
-                final String value = parameters.get(key);
-                final String encodedValue = StringUtil.urlEncode(value);
-
-                output.append(output.toString().contains("?") ? "&" : "?");
-                output.append(key);
-                output.append("=");
-                output.append(encodedValue);
-            }
-        }
-
-        if (output.charAt(0) == '?' || output.charAt(0) == '&') {
-            output.deleteCharAt(0);
-        }
-
-        return output.toString();
-    }
-}

+ 1 - 5
src/main/java/password/pwm/http/filter/ConfigAccessFilter.java

@@ -16,7 +16,6 @@ import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.ContextManager;
 import password.pwm.http.PwmRequest;
 import password.pwm.http.PwmSession;
-import password.pwm.http.ServletHelper;
 import password.pwm.http.bean.ConfigManagerBean;
 import password.pwm.ldap.auth.AuthenticationType;
 import password.pwm.svc.intruder.RecordType;
@@ -127,10 +126,7 @@ public class ConfigAccessFilter extends AbstractPwmFilter {
             }
 
             {
-                final String cookieStr = ServletHelper.readCookie(
-                        pwmRequest.getHttpServletRequest(),
-                        PwmConstants.COOKIE_PERSISTENT_CONFIG_LOGIN
-                );
+                final String cookieStr = pwmRequest.readCookie(PwmConstants.COOKIE_PERSISTENT_CONFIG_LOGIN);
                 if (securityKey != null && cookieStr != null && !cookieStr.isEmpty()) {
                     try {
                         final String jsonStr = pwmApplication.getSecureService().decryptStringValue(cookieStr);

+ 355 - 7
src/main/java/password/pwm/http/filter/RequestInitializationFilter.java

@@ -25,20 +25,32 @@ package password.pwm.http.filter;
 import password.pwm.AppProperty;
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
+import password.pwm.bean.LocalSessionStateBean;
+import password.pwm.config.Configuration;
+import password.pwm.config.PwmSetting;
 import password.pwm.error.ErrorInformation;
 import password.pwm.error.PwmError;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.*;
+import password.pwm.svc.stats.Statistic;
+import password.pwm.svc.stats.StatisticsManager;
+import password.pwm.util.IPMatcher;
+import password.pwm.util.LocaleHelper;
+import password.pwm.util.StringUtil;
+import password.pwm.util.TimeDuration;
 import password.pwm.util.logging.PwmLogger;
+import password.pwm.util.macro.MacroMachine;
+import password.pwm.util.secure.PwmRandom;
 
 import javax.servlet.*;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 import java.io.IOException;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.*;
 
 public class RequestInitializationFilter implements Filter {
 
@@ -57,9 +69,9 @@ public class RequestInitializationFilter implements Filter {
 
     @Override
     public void doFilter(
-            ServletRequest servletRequest,
-            ServletResponse servletResponse,
-            FilterChain filterChain
+            final ServletRequest servletRequest,
+            final ServletResponse servletResponse,
+            final FilterChain filterChain
     )
             throws IOException, ServletException
     {
@@ -68,10 +80,48 @@ public class RequestInitializationFilter implements Filter {
 
         try {
             checkAndInitSessionState(req);
+            PwmRequest.forRequest(req,resp);
+        } catch (Throwable e) {
+            LOGGER.error("can't load application: " + e.getMessage(),e);
+            if (!(new PwmURL(req).isResourceURL())) {
+                ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_APP_UNAVAILABLE);
+                try {
+                    ContextManager contextManager = ContextManager.getContextManager(servletRequest.getServletContext());
+                    if (contextManager != null) {
+                        errorInformation = contextManager.getStartupErrorInformation();
+                    }
+                } catch (Throwable e2) {
+                    e2.getMessage();
+                }
+                servletRequest.setAttribute(PwmRequest.Attribute.PwmErrorInfo.toString(),errorInformation);
+                final String url = PwmConstants.JSP_URL.APP_UNAVAILABLE.getPath();
+                servletRequest.getServletContext().getRequestDispatcher(url).forward(req, resp);
+            }
+            return;
+        }
+
+        try {
             final PwmRequest pwmRequest = PwmRequest.forRequest(req,resp);
+
             checkIfSessionRecycleNeeded(pwmRequest);
+
+            addPwmResponseHeaders(pwmRequest);
+
+            handleRequestInitialization(pwmRequest);
+
+            try {
+                handleRequestSecurityChecks(pwmRequest);
+            } catch (PwmUnrecoverableException e) {
+                LOGGER.error(pwmRequest, e.getErrorInformation());
+                pwmRequest.respondWithError(e.getErrorInformation());
+                if (PwmError.ERROR_INTRUDER_SESSION != e.getError()) {
+                    pwmRequest.invalidateSession();
+                }
+                return;
+            }
+
         } catch (Throwable e) {
-            LOGGER.error("can't load application: " + e.getMessage(),e);
+            LOGGER.error("can't init request: " + e.getMessage(),e);
             if (!(new PwmURL(req).isResourceURL())) {
                 ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_APP_UNAVAILABLE);
                 try {
@@ -165,5 +215,303 @@ public class RequestInitializationFilter implements Filter {
         pwmRequest.getPwmSession().getSessionStateBean().setSessionIdRecycleNeeded(false);
     }
 
+    public static void addPwmResponseHeaders(
+            final PwmRequest pwmRequest
+    ) throws PwmUnrecoverableException {
+
+        if (pwmRequest == null) {
+            return;
+        }
+        final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
+        final PwmSession pwmSession = pwmRequest.getPwmSession();
+        final PwmResponse resp = pwmRequest.getPwmResponse();
+
+        if (resp.isCommitted()) {
+            return;
+        }
+
+        final String serverHeader = pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_HEADER_SERVER);
+
+        final boolean includeXInstance = Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_HEADER_SEND_XINSTANCE));
+        final boolean includeXSessionID = Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_HEADER_SEND_XSESSIONID));
+        final boolean includeXVersion = Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_HEADER_SEND_XVERSION));
+        final boolean includeXContentTypeOptions = Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_HEADER_SEND_XCONTENTTYPEOPTIONS));
+        final boolean includeXXSSProtection = Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_HEADER_SEND_XXSSPROTECTION));
+
+        final boolean sendNoise = Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_HEADER_SEND_XNOISE));
+
+        if (sendNoise) {
+            resp.setHeader(
+                    PwmConstants.HttpHeader.XNoise,
+                    PwmRandom.getInstance().alphaNumericString(PwmRandom.getInstance().nextInt(100)+10)
+            );
+        }
+
+        if (includeXVersion) {
+            resp.setHeader(PwmConstants.HttpHeader.XVersion, PwmConstants.SERVLET_VERSION);
+        }
+
+        if (includeXContentTypeOptions) {
+            resp.setHeader(PwmConstants.HttpHeader.XContentTypeOptions, "nosniff");
+        }
+
+        if (includeXXSSProtection) {
+            resp.setHeader(PwmConstants.HttpHeader.XXSSProtection, "1");
+        }
+
+        if (includeXInstance) {
+            resp.setHeader(PwmConstants.HttpHeader.XInstance, String.valueOf(pwmApplication.getInstanceID()));
+        }
+
+        if (includeXSessionID && pwmSession != null) {
+            resp.setHeader(PwmConstants.HttpHeader.XSessionID, pwmSession.getSessionStateBean().getSessionID());
+        }
+
+        if (serverHeader != null && !serverHeader.isEmpty()) {
+            final String value = MacroMachine.forNonUserSpecific(pwmApplication, null).expandMacros(serverHeader);
+            resp.setHeader(PwmConstants.HttpHeader.Server, value);
+        }
+
+        if (pwmRequest.getURL().isResourceURL()) {
+            return;
+        }
+
+        final boolean includeXFrameDeny = pwmApplication.getConfig().readSettingAsBoolean(PwmSetting.SECURITY_PREVENT_FRAMING);
+        final boolean includeXAmb = Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_HEADER_SEND_XAMB));
+
+        if (includeXFrameDeny) {
+            resp.setHeader(PwmConstants.HttpHeader.XFrameOptions, "DENY");
+        }
+
+        if (includeXAmb) {
+            resp.setHeader(PwmConstants.HttpHeader.XAmb, PwmConstants.X_AMB_HEADER[PwmRandom.getInstance().nextInt(PwmConstants.X_AMB_HEADER.length)]);
+        }
+
+        resp.setHeader(PwmConstants.HttpHeader.Cache_Control, "no-cache, no-store, must-revalidate, proxy-revalidate");
+
+        if (pwmSession != null) {
+            final String contentPolicy = pwmApplication.getConfig().readSettingAsString(PwmSetting.SECURITY_CSP_HEADER);
+            if (contentPolicy != null && !contentPolicy.isEmpty()) {
+                final String nonce = pwmRequest.getCspNonce();
+                final String expandedPolicy = contentPolicy.replace("%NONCE%", nonce);
+                resp.setHeader(PwmConstants.HttpHeader.ContentSecurityPolicy, expandedPolicy);
+            }
+        }
+    }
+
+
+    public static String readUserHostname(final PwmRequest pwmRequest) throws PwmUnrecoverableException {
+        final Configuration config = pwmRequest.getConfig();
+        if (config != null && !config.readSettingAsBoolean(PwmSetting.REVERSE_DNS_ENABLE)) {
+            return "";
+        }
+
+        final String userIPAddress = readUserIPAddress(pwmRequest);
+        try {
+            return InetAddress.getByName(userIPAddress).getCanonicalHostName();
+        } catch (UnknownHostException e) {
+            LOGGER.trace(pwmRequest, "unknown host while trying to compute hostname for src request: " + e.getMessage());
+        }
+        return "";
+    }
+
+    /**
+     * Returns the IP address of the user.  If there is an X-Forwarded-For header in the request, that address will
+     * be used.  Otherwise, the source address of the request is used.
+     *
+     * @return String containing the textual representation of the source IP address, or null if the request is invalid.
+     */
+    public static String readUserIPAddress(final PwmRequest pwmRequest) throws PwmUnrecoverableException {
+        final Configuration config = pwmRequest.getConfig();
+        final boolean useXForwardedFor = config != null && config.readSettingAsBoolean(PwmSetting.USE_X_FORWARDED_FOR_HEADER);
+
+        String userIP = "";
+
+        if (useXForwardedFor) {
+            try {
+                userIP = pwmRequest.readHeaderValueAsString(PwmConstants.HTTP_HEADER_X_FORWARDED_FOR);
+            } catch (Exception e) {
+                //ip address not in header (no X-Forwarded-For)
+            }
+        }
+
+        if (userIP == null || userIP.length() < 1) {
+            userIP = pwmRequest.getHttpServletRequest().getRemoteAddr();
+        }
+
+        return userIP == null ? "" : userIP;
+    }
+
+
+    public static void handleRequestInitialization(
+            final PwmRequest pwmRequest
+    )
+            throws PwmUnrecoverableException
+    {
+        final LocalSessionStateBean ssBean = pwmRequest.getPwmSession().getSessionStateBean();
+        final PwmURL pwmURL = pwmRequest.getURL();
+
+        // mark if first request
+        if (ssBean.getSessionCreationTime() == null) {
+            ssBean.setSessionCreationTime(new Date());
+            ssBean.setSessionLastAccessedTime(new Date());
+        }
+
+        // mark session ip address
+        if (ssBean.getSrcAddress() == null) {
+            ssBean.setSrcAddress(readUserIPAddress(pwmRequest));
+        }
+
+        // mark the user's hostname in the session bean
+        if (ssBean.getSrcHostname() == null) {
+            ssBean.setSrcHostname(readUserHostname(pwmRequest));
+        }
+
+        // update the privateUrlAccessed flag
+        if (pwmURL.isPrivateUrl()) {
+            ssBean.setPrivateUrlAccessed(true);
+        }
+
+        // initialize the session's locale
+        if (ssBean.getLocale() == null) {
+            initializeLocaleAndTheme(pwmRequest);
+        }
+
+        // set idle timeout (may get overridden by module-specific values elsewhere
+        if (!pwmURL.isResourceURL() && !pwmURL.isCommandServletURL() && !pwmURL.isWebServiceURL()){
+            final int sessionIdleSeconds = (int) pwmRequest.getConfig().readSettingAsLong(PwmSetting.IDLE_TIMEOUT_SECONDS);
+            pwmRequest.getPwmSession().setSessionTimeout(pwmRequest.getHttpServletRequest().getSession(), sessionIdleSeconds);
+        }
+    }
+
+    private static void initializeLocaleAndTheme(
+            final PwmRequest pwmRequest
+    )
+            throws PwmUnrecoverableException
+    {
+        final String localeCookieName = pwmRequest.getConfig().readAppProperty(AppProperty.HTTP_COOKIE_LOCALE_NAME);
+        final String localeCookie = pwmRequest.readCookie(localeCookieName);
+        if (localeCookieName.length() > 0 && localeCookie != null) {
+            LOGGER.debug(pwmRequest, "detected locale cookie in request, setting locale to " + localeCookie);
+            pwmRequest.getPwmSession().setLocale(pwmRequest.getPwmApplication(), localeCookie);
+        } else {
+            final List<Locale> knownLocales = pwmRequest.getConfig().getKnownLocales();
+            final Locale userLocale = LocaleHelper.localeResolver(pwmRequest.getLocale(), knownLocales);
+            pwmRequest.getPwmSession().getSessionStateBean().setLocale(userLocale == null ? PwmConstants.DEFAULT_LOCALE : userLocale);
+            LOGGER.trace(pwmRequest, "user locale set to '" + pwmRequest.getLocale() + "'");
+        }
+
+        final String themeCookieName = pwmRequest.getConfig().readAppProperty(AppProperty.HTTP_COOKIE_THEME_NAME);
+        final String themeCookie = pwmRequest.readCookie(themeCookieName);
+        if (localeCookieName.length() > 0 && themeCookie != null && themeCookie.length() > 0) {
+            if (pwmRequest.getPwmApplication().getResourceServletService().checkIfThemeExists(pwmRequest, themeCookie)) {
+                LOGGER.debug(pwmRequest, "detected theme cookie in request, setting theme to " + themeCookie);
+                pwmRequest.getPwmSession().getSessionStateBean().setTheme(themeCookie);
+            }
+        }
+    }
+
+    public static void handleRequestSecurityChecks(
+            final PwmRequest pwmRequest
+    )
+            throws PwmUnrecoverableException
+    {
+        final LocalSessionStateBean ssBean = pwmRequest.getPwmSession().getSessionStateBean();
+
+        // check the user's IP address
+        if (!pwmRequest.getConfig().readSettingAsBoolean(PwmSetting.MULTI_IP_SESSION_ALLOWED)) {
+            final String remoteAddress = readUserIPAddress(pwmRequest);
+            if (!ssBean.getSrcAddress().equals(remoteAddress)) {
+                final String errorMsg = "current network address '" + remoteAddress + "' has changed from original network address '" + ssBean.getSrcAddress() + "'";
+                final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION,errorMsg);
+                throw new PwmUnrecoverableException(errorInformation);
+            }
+        }
+
+        // check total time.
+        {
+            if (ssBean.getSessionCreationTime() != null) {
+                final Long maxSessionSeconds = pwmRequest.getConfig().readSettingAsLong(PwmSetting.SESSION_MAX_SECONDS);
+                final TimeDuration sessionAge = TimeDuration.fromCurrent(ssBean.getSessionCreationTime());
+                if (sessionAge.getTotalSeconds() > maxSessionSeconds) {
+                    final String errorMsg = "session age (" + sessionAge.asCompactString() + ") is longer than maximum permitted age";
+                    final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION,errorMsg);
+                    throw new PwmUnrecoverableException(errorInformation);
+                }
+            }
+        }
+
+        // check headers
+        {
+            final List<String> requiredHeaders = pwmRequest.getConfig().readSettingAsStringArray(PwmSetting.REQUIRED_HEADERS);
+            if (requiredHeaders != null && !requiredHeaders.isEmpty()) {
+                final Map<String, String> configuredValues  = StringUtil.convertStringListToNameValuePair(requiredHeaders, "=");
+                for (final String key : configuredValues.keySet()) {
+                    if (key != null && key.length() > 0) {
+                        final String requiredValue = configuredValues.get(key);
+                        if (requiredValue != null && requiredValue.length() > 0) {
+                            final String value = pwmRequest.readHeaderValueAsString(key);
+                            if (value == null || value.length() < 1) {
+                                final String errorMsg = "request is missing required value for header '" + key + "'";
+                                final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION,errorMsg);
+                                throw new PwmUnrecoverableException(errorInformation);
+                            } else {
+                                if (!requiredValue.equals(value)) {
+                                    final String errorMsg = "request has incorrect required value for header '" + key + "'";
+                                    final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SECURITY_VIOLATION,errorMsg);
+                                    throw new PwmUnrecoverableException(errorInformation);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // check permitted source IP address
+        {
+            final List<String> requiredHeaders = pwmRequest.getConfig().readSettingAsStringArray(PwmSetting.IP_PERMITTED_RANGE);
+            if (requiredHeaders != null && !requiredHeaders.isEmpty()) {
+                boolean match = false;
+                final String requestAddress = pwmRequest.getHttpServletRequest().getRemoteAddr();
+                for (int i = 0; i < requiredHeaders.size() && !match; i++) {
+                    String ipMatchString = requiredHeaders.get(i);
+                    try {
+                        final IPMatcher ipMatcher = new IPMatcher(ipMatchString);
+                        try {
+                            if (ipMatcher.match(requestAddress)) {
+                                match = true;
+                            }
+                        } catch (IPMatcher.IPMatcherException e) {
+                            LOGGER.error("error while attempting to match permitted address range '" + ipMatchString + "', error: " + e);
+                        }
+                    } catch (IPMatcher.IPMatcherException e) {
+                        LOGGER.error("error parsing permitted address range '" + ipMatchString + "', error: " + e);
+                    }
+                }
+                if (!match) {
+                    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);
+                }
+            }
+        }
+
+        // check trial
+        if (PwmConstants.TRIAL_MODE) {
+            final String currentAuthString = pwmRequest.getPwmApplication().getStatisticsManager().getStatBundleForKey(StatisticsManager.KEY_CURRENT).getStatistic(Statistic.AUTHENTICATIONS);
+            if (new BigInteger(currentAuthString).compareTo(BigInteger.valueOf(PwmConstants.TRIAL_MAX_AUTHENTICATIONS)) > 0) {
+                throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_TRIAL_VIOLATION,"maximum usage per server startup exceeded"));
+            }
+
+            final String totalAuthString = pwmRequest.getPwmApplication().getStatisticsManager().getStatBundleForKey(StatisticsManager.KEY_CUMULATIVE).getStatistic(Statistic.AUTHENTICATIONS);
+            if (new BigInteger(totalAuthString).compareTo(BigInteger.valueOf(PwmConstants.TRIAL_MAX_TOTAL_AUTH)) > 0) {
+                throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_TRIAL_VIOLATION,"maximum usage for this server has been exceeded"));
+            }
+        }
+
+        // check intruder
+        pwmRequest.getPwmApplication().getIntruderManager().convenience().checkAddressAndSession(pwmRequest.getPwmSession());
+    }
 
 }

+ 1 - 17
src/main/java/password/pwm/http/filter/SessionFilter.java

@@ -110,22 +110,10 @@ public class SessionFilter extends AbstractPwmFilter {
         final LocalSessionStateBean ssBean = pwmSession.getSessionStateBean();
         final PwmResponse resp = pwmRequest.getPwmResponse();
 
-        ServletHelper.handleRequestInitialization(pwmRequest, pwmApplication, pwmSession);
-
-        try {
-            ServletHelper.handleRequestSecurityChecks(pwmRequest.getHttpServletRequest(), pwmApplication, pwmSession);
-        } catch (PwmUnrecoverableException e) {
-            LOGGER.error(pwmRequest, e.getErrorInformation());
-            pwmRequest.respondWithError(e.getErrorInformation());
-            if (PwmError.ERROR_INTRUDER_SESSION != e.getError()) {
-                pwmRequest.invalidateSession();
-            }
-            return false;
-        }
 
         // debug the http session headers
         if (!pwmSession.getSessionStateBean().isDebugInitialized()) {
-            LOGGER.trace(pwmSession, ServletHelper.debugHttpHeaders(pwmRequest.getHttpServletRequest()));
+            LOGGER.trace(pwmSession, pwmRequest.debugHttpHeaders());
             pwmSession.getSessionStateBean().setDebugInitialized(true);
         }
 
@@ -228,10 +216,6 @@ public class SessionFilter extends AbstractPwmFilter {
             pwmSession.getUserInfoBean().getPasswordState().setExpired(true);
         }
 
-        if (!resp.isCommitted()) {
-            ServletHelper.addPwmResponseHeaders(pwmRequest, true);
-        }
-
         // update last request time.
         ssBean.setSessionLastAccessedTime(new Date());
 

+ 1 - 2
src/main/java/password/pwm/http/servlet/CaptchaServlet.java

@@ -37,7 +37,6 @@ import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.HttpMethod;
 import password.pwm.http.PwmRequest;
 import password.pwm.http.PwmSession;
-import password.pwm.http.ServletHelper;
 import password.pwm.http.client.PwmHttpClient;
 import password.pwm.http.client.PwmHttpClientRequest;
 import password.pwm.http.client.PwmHttpClientResponse;
@@ -279,7 +278,7 @@ public class CaptchaServlet extends AbstractPwmServlet {
         final String allowedSkipValue = figureSkipCookieValue(pwmRequest);
         final String captchaSkipCookieName = pwmRequest.getConfig().readAppProperty(AppProperty.HTTP_COOKIE_CAPTCHA_SKIP_NAME);
         if (allowedSkipValue != null) {
-            final String cookieValue = ServletHelper.readCookie(pwmRequest.getHttpServletRequest(), captchaSkipCookieName);
+            final String cookieValue = pwmRequest.readCookie(captchaSkipCookieName);
             if (allowedSkipValue.equals(cookieValue)) {
                 LOGGER.debug(pwmRequest, "browser has a valid " + captchaSkipCookieName+ " cookie value of " + figureSkipCookieValue(pwmRequest) + ", skipping captcha check");
                 return true;

+ 1 - 2
src/main/java/password/pwm/http/servlet/LoginServlet.java

@@ -30,7 +30,6 @@ import password.pwm.error.*;
 import password.pwm.http.HttpMethod;
 import password.pwm.http.PwmRequest;
 import password.pwm.http.PwmURL;
-import password.pwm.http.ServletHelper;
 import password.pwm.ldap.auth.AuthenticationType;
 import password.pwm.ldap.auth.PwmAuthenticationSource;
 import password.pwm.ldap.auth.SessionAuthenticator;
@@ -256,7 +255,7 @@ public class LoginServlet extends AbstractPwmServlet {
 
         final String encryptedRedirUrl = pwmRequest.getPwmApplication().getSecureService().encryptToString(originalRequestedUrl);
 
-        final String redirectUrl = ServletHelper.appendAndEncodeUrlParameters(
+        final String redirectUrl = PwmURL.appendAndEncodeUrlParameters(
                 pwmRequest.getContextPath() + PwmServletDefinition.Login.servletUrl(),
                 Collections.singletonMap(PwmConstants.PARAM_POST_LOGIN_URL, encryptedRedirUrl)
         );

+ 3 - 6
src/main/java/password/pwm/http/servlet/LogoutServlet.java

@@ -28,10 +28,7 @@ import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
 import password.pwm.config.PwmSetting;
 import password.pwm.error.PwmUnrecoverableException;
-import password.pwm.http.HttpMethod;
-import password.pwm.http.PwmRequest;
-import password.pwm.http.PwmSession;
-import password.pwm.http.ServletHelper;
+import password.pwm.http.*;
 import password.pwm.util.logging.PwmLogger;
 
 import javax.servlet.ServletException;
@@ -126,7 +123,7 @@ public class LogoutServlet extends AbstractPwmServlet {
                     }
                 }
 
-                final String logoutURL = ServletHelper.appendAndEncodeUrlParameters(configuredLogoutURL, logoutUrlParameters);
+                final String logoutURL = PwmURL.appendAndEncodeUrlParameters(configuredLogoutURL, logoutUrlParameters);
 
                 LOGGER.trace(pwmSession, "redirecting user to configured logout url:" + logoutURL.toString());
                 pwmRequest.sendRedirect(logoutURL.toString());
@@ -136,7 +133,7 @@ public class LogoutServlet extends AbstractPwmServlet {
         }
 
         // if we didn't go anywhere yet, then show the pwm logout jsp
-        final String logoutURL = ServletHelper.appendAndEncodeUrlParameters(
+        final String logoutURL = PwmURL.appendAndEncodeUrlParameters(
                 pwmRequest.getContextPath() + PwmServletDefinition.Logout.servletUrl(),
                 Collections.singletonMap(PwmConstants.PARAM_ACTION_REQUEST, LogoutAction.showLogout.toString())
         );

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

@@ -143,7 +143,7 @@ public class ConfigGuideServlet extends AbstractPwmServlet {
 
         if (!configGuideBean.getFormData().containsKey(ConfigGuideForm.FormParameter.PARAM_APP_SITEURL)) {
             final URI uri = URI.create(pwmRequest.getHttpServletRequest().getRequestURL().toString());
-            final int port = Helper.portForUriSchema(uri);
+            final int port = PwmURL.portForUriSchema(uri);
             final String newUri = uri.getScheme() + "://" + uri.getHost() + ":" + port + pwmRequest.getContextPath();
             configGuideBean.getFormData().put(ConfigGuideForm.FormParameter.PARAM_APP_SITEURL,newUri);
         }
@@ -230,7 +230,7 @@ public class ConfigGuideServlet extends AbstractPwmServlet {
         }
 
         if (ServletFileUpload.isMultipartContent(req)) {
-            final InputStream uploadedFile = ServletHelper.readFileUpload(req,"uploadFile");
+            final InputStream uploadedFile = pwmRequest.readFileUploadStream(PwmConstants.PARAM_FILE_UPLOAD);
             if (uploadedFile != null) {
                 try {
                     final StoredConfigurationImpl storedConfig = StoredConfigurationImpl.fromXml(uploadedFile);

+ 1 - 3
src/main/java/password/pwm/http/servlet/configmanager/ConfigManagerLocalDBServlet.java

@@ -152,7 +152,7 @@ public class ConfigManagerLocalDBServlet extends AbstractPwmServlet {
             return;
         }
 
-        final InputStream inputStream = ServletHelper.readFileUpload(pwmRequest.getHttpServletRequest(), "uploadFile");
+        final InputStream inputStream = pwmRequest.readFileUploadStream(PwmConstants.PARAM_FILE_UPLOAD);
 
         final ContextManager contextManager = ContextManager.getContextManager(pwmRequest);
         LocalDB localDB = null;
@@ -187,7 +187,5 @@ public class ConfigManagerLocalDBServlet extends AbstractPwmServlet {
 
         pwmRequest.outputJsonResult(RestResultBean.forSuccessMessage(pwmRequest, Message.Success_Unknown));
     }
-
-
 }
 

+ 1 - 1
src/main/java/password/pwm/http/servlet/configmanager/ConfigManagerServlet.java

@@ -180,7 +180,7 @@ public class ConfigManagerServlet extends AbstractPwmServlet {
             return;
         }
 
-        final InputStream inputStream = ServletHelper.readFileUpload(pwmRequest.getHttpServletRequest(),"uploadFile");
+        final InputStream inputStream = pwmRequest.readFileUploadStream(PwmConstants.PARAM_FILE_UPLOAD);
         try {
             pwmApplication.getWordlistManager().populate(inputStream);
         } catch (PwmUnrecoverableException e) {

+ 1 - 2
src/main/java/password/pwm/http/servlet/configmanager/ConfigManagerWordlistServlet.java

@@ -31,7 +31,6 @@ import password.pwm.error.PwmError;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.HttpMethod;
 import password.pwm.http.PwmRequest;
-import password.pwm.http.ServletHelper;
 import password.pwm.http.servlet.AbstractPwmServlet;
 import password.pwm.i18n.Message;
 import password.pwm.svc.wordlist.StoredWordlistDataBean;
@@ -138,7 +137,7 @@ public class ConfigManagerWordlistServlet extends AbstractPwmServlet {
             return;
         }
 
-        final InputStream inputStream = ServletHelper.readFileUpload(pwmRequest.getHttpServletRequest(),"uploadFile");
+        final InputStream inputStream = pwmRequest.readFileUploadStream(PwmConstants.PARAM_FILE_UPLOAD);
 
         try {
             wordlistType.forType(pwmApplication).populate(inputStream);

+ 1 - 1
src/main/java/password/pwm/http/servlet/configmanager/DebugItemGenerator.java

@@ -177,7 +177,7 @@ public class DebugItemGenerator {
                 }
             };
 
-            final Map<PwmAboutProperty,String> infoBean = Helper.makeInfoBean(pwmApplication);
+            final Map<PwmAboutProperty,String> infoBean = PwmAboutProperty.makeInfoBean(pwmApplication);
             for (final PwmAboutProperty aboutProperty : infoBean.keySet()) {
                 outputProps.put(aboutProperty.toString().replace("_","."), infoBean.get(aboutProperty));
             }

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

@@ -789,18 +789,18 @@ public class HelpdeskServlet extends AbstractPwmServlet {
         }
 
         StatisticsManager.incrementStat(pwmRequest,Statistic.HELPDESK_TOKENS_SENT);
-        final HelpdeskTokenValidationBean helpdeskTokenValidationBean = new HelpdeskTokenValidationBean();
-        helpdeskTokenValidationBean.setDestination(destDisplayString.toString());
-        helpdeskTokenValidationBean.setUserKey(bodyParams.get("userKey"));
+        final HelpdeskVerificationRequestBean helpdeskVerificationRequestBean = new HelpdeskVerificationRequestBean();
+        helpdeskVerificationRequestBean.setDestination(destDisplayString.toString());
+        helpdeskVerificationRequestBean.setUserKey(bodyParams.get("userKey"));
 
-        final HelpdeskTokenValidationBean.TokenData tokenData = new HelpdeskTokenValidationBean.TokenData();
+        final HelpdeskVerificationRequestBean.TokenData tokenData = new HelpdeskVerificationRequestBean.TokenData();
         tokenData.setToken(tokenKey);
         tokenData.setIssueDate(new Date());
 
         final SecureService secureService = pwmRequest.getPwmApplication().getSecureService();
-        helpdeskTokenValidationBean.setTokenData(secureService.encryptObjectToString(tokenData));
+        helpdeskVerificationRequestBean.setTokenData(secureService.encryptObjectToString(tokenData));
 
-        final RestResultBean restResultBean = new RestResultBean(helpdeskTokenValidationBean);
+        final RestResultBean restResultBean = new RestResultBean(helpdeskVerificationRequestBean);
         pwmRequest.outputJsonResult(restResultBean);
         LOGGER.debug(pwmRequest, "helpdesk operator "
                 + pwmRequest.getUserInfoIfLoggedIn().toDisplayString()
@@ -816,19 +816,19 @@ public class HelpdeskServlet extends AbstractPwmServlet {
     )
             throws IOException, PwmUnrecoverableException, ServletException
     {
-        final HelpdeskTokenValidationBean helpdeskTokenValidationBean =JsonUtil.deserialize(
+        final HelpdeskVerificationRequestBean helpdeskVerificationRequestBean =JsonUtil.deserialize(
                 pwmRequest.readRequestBodyAsString(),
-                HelpdeskTokenValidationBean.class
+                HelpdeskVerificationRequestBean.class
         );
-        final String token = helpdeskTokenValidationBean.getCode();
+        final String token = helpdeskVerificationRequestBean.getCode();
 
         final SecureService secureService = pwmRequest.getPwmApplication().getSecureService();
-        final HelpdeskTokenValidationBean.TokenData tokenData = secureService.decryptObject(
-                helpdeskTokenValidationBean.getTokenData(),
-                HelpdeskTokenValidationBean.TokenData.class
+        final HelpdeskVerificationRequestBean.TokenData tokenData = secureService.decryptObject(
+                helpdeskVerificationRequestBean.getTokenData(),
+                HelpdeskVerificationRequestBean.TokenData.class
         );
 
-        final UserIdentity userIdentity = UserIdentity.fromKey(helpdeskTokenValidationBean.getUserKey(), pwmRequest.getPwmApplication());
+        final UserIdentity userIdentity = UserIdentity.fromKey(helpdeskVerificationRequestBean.getUserKey(), pwmRequest.getPwmApplication());
 
         if (tokenData == null || tokenData.getIssueDate() == null || tokenData.getToken() == null || tokenData.getToken().isEmpty()) {
             final String errorMsg = "token data is corrupted";

+ 1 - 1
src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskTokenValidationBean.java → src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskVerificationRequestBean.java

@@ -3,7 +3,7 @@ package password.pwm.http.servlet.helpdesk;
 import java.io.Serializable;
 import java.util.Date;
 
-public class HelpdeskTokenValidationBean implements Serializable {
+public class HelpdeskVerificationRequestBean implements Serializable {
 
     private String destination;
     private String userKey;

+ 21 - 0
src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskVerificationResponseBean.java

@@ -0,0 +1,21 @@
+package password.pwm.http.servlet.helpdesk;
+
+import java.io.Serializable;
+
+public class HelpdeskVerificationResponseBean implements Serializable {
+    private boolean passed;
+    private HelpdeskVerificationStateBean verificationState;
+
+    public HelpdeskVerificationResponseBean(boolean passed, HelpdeskVerificationStateBean verificationState) {
+        this.passed = passed;
+        this.verificationState = verificationState;
+    }
+
+    public boolean isPassed() {
+        return passed;
+    }
+
+    public HelpdeskVerificationStateBean getVerificationState() {
+        return verificationState;
+    }
+}

+ 43 - 0
src/main/java/password/pwm/http/servlet/helpdesk/HelpdeskVerificationStateBean.java

@@ -0,0 +1,43 @@
+package password.pwm.http.servlet.helpdesk;
+
+import password.pwm.bean.UserIdentity;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+public class HelpdeskVerificationStateBean implements Serializable {
+    private UserIdentity actor;
+    private List<HelpdeskValidationRecord> records;
+
+    public HelpdeskVerificationStateBean(UserIdentity actor, List<HelpdeskValidationRecord> records) {
+        this.actor = actor;
+        this.records = records;
+    }
+
+    public UserIdentity getActor() {
+        return actor;
+    }
+
+    public List<HelpdeskValidationRecord> getRecords() {
+        return records;
+    }
+
+    static class HelpdeskValidationRecord {
+        private Date timestamp;
+        private UserIdentity identity;
+
+        public HelpdeskValidationRecord(Date timestamp, UserIdentity identity) {
+            this.timestamp = timestamp;
+            this.identity = identity;
+        }
+
+        public Date getTimestamp() {
+            return timestamp;
+        }
+
+        public UserIdentity getIdentity() {
+            return identity;
+        }
+    }
+}

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

@@ -38,7 +38,7 @@ import password.pwm.config.PwmSetting;
 import password.pwm.error.*;
 import password.pwm.http.PwmRequest;
 import password.pwm.http.PwmSession;
-import password.pwm.http.ServletHelper;
+import password.pwm.http.PwmURL;
 import password.pwm.bean.LoginInfoBean;
 import password.pwm.http.client.PwmHttpClient;
 import password.pwm.http.client.PwmHttpClientConfiguration;
@@ -406,7 +406,7 @@ public class OAuthConsumerServlet extends AbstractPwmServlet {
             throws IOException, PwmUnrecoverableException
     {
         final Date startTime = new Date();
-        final String requestBody = ServletHelper.appendAndEncodeUrlParameters("", requestParams);
+        final String requestBody = PwmURL.appendAndEncodeUrlParameters("", requestParams);
         LOGGER.trace(pwmRequest, "beginning " + debugText + " request to " + requestUrl + ", body: \n" + requestBody);
         final HttpPost httpPost = new HttpPost(requestUrl);
         httpPost.setHeader(PwmConstants.HttpHeader.Authorization.getHttpName(),
@@ -518,7 +518,7 @@ public class OAuthConsumerServlet extends AbstractPwmServlet {
         urlParams.put(config.readAppProperty(AppProperty.HTTP_PARAM_OAUTH_STATE),state);
         urlParams.put(config.readAppProperty(AppProperty.HTTP_PARAM_OAUTH_REDIRECT_URI), redirectUri);
 
-        final String redirectUrl = ServletHelper.appendAndEncodeUrlParameters(settings.getLoginURL(), urlParams);
+        final String redirectUrl = PwmURL.appendAndEncodeUrlParameters(settings.getLoginURL(), urlParams);
 
         try{
             pwmRequest.sendRedirect(redirectUrl);

+ 0 - 5
src/main/java/password/pwm/http/servlet/resource/ResourceFileServlet.java

@@ -31,7 +31,6 @@ import password.pwm.error.PwmError;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.HttpMethod;
 import password.pwm.http.PwmRequest;
-import password.pwm.http.ServletHelper;
 import password.pwm.http.servlet.PwmServlet;
 import password.pwm.svc.stats.EventRateMeter;
 import password.pwm.svc.stats.Statistic;
@@ -187,7 +186,6 @@ public class ResourceFileServlet extends HttpServlet implements PwmServlet {
             if (ifNoneMatchValue != null && ifNoneMatchValue.equals(eTagValue)) {
                 response.reset();
                 response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
-                ServletHelper.addPwmResponseHeaders(pwmRequest, false);
                 try {
                     pwmRequest.debugHttpRequestToLog("returning HTTP 304 status");
                 } catch (PwmUnrecoverableException e2) { /* noop */ }
@@ -201,9 +199,6 @@ public class ResourceFileServlet extends HttpServlet implements PwmServlet {
         response.setHeader("ETag", resourceConfiguration.getNonceValue());
         response.setContentType(contentType);
 
-        // set pwm headers
-        ServletHelper.addPwmResponseHeaders(pwmRequest, false);
-
         try {
             boolean fromCache = false;
             StringBuilder debugText = new StringBuilder();

+ 0 - 4
src/main/java/password/pwm/svc/wordlist/AbstractWordlist.java

@@ -207,10 +207,6 @@ abstract class AbstractWordlist implements Wordlist, PwmService {
             }
         }
 
-        if (wlStatus != STATUS.CLOSED) {
-            LOGGER.debug("closed");
-        }
-
         wlStatus = STATUS.CLOSED;
         localDB = null;
     }

+ 0 - 133
src/main/java/password/pwm/util/Helper.java

@@ -26,7 +26,6 @@ import com.novell.ldapchai.ChaiUser;
 import com.novell.ldapchai.exception.ChaiOperationException;
 import com.novell.ldapchai.exception.ChaiUnavailableException;
 import org.apache.commons.csv.CSVPrinter;
-import password.pwm.PwmAboutProperty;
 import password.pwm.PwmApplication;
 import password.pwm.PwmConstants;
 import password.pwm.bean.FormNonce;
@@ -39,11 +38,8 @@ import password.pwm.error.PwmOperationalException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.PwmRequest;
 import password.pwm.http.PwmSession;
-import password.pwm.i18n.Display;
-import password.pwm.util.db.DatabaseAccessor;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.macro.MacroMachine;
-import password.pwm.util.secure.PwmRandom;
 
 import java.io.*;
 import java.lang.reflect.Method;
@@ -435,135 +431,6 @@ public class
         return new CSVPrinter(new OutputStreamWriter(outputStream,PwmConstants.DEFAULT_CHARSET), PwmConstants.DEFAULT_CSV_FORMAT);
     }
 
-    private static String dateFormatForInfoBean(final Date date) {
-        if (date != null) {
-            return PwmConstants.DEFAULT_DATETIME_FORMAT.format(date);
-        } else {
-            return LocaleHelper.getLocalizedMessage(PwmConstants.DEFAULT_LOCALE, Display.Value_NotApplicable, null);
-        }
-
-    }
-
-    public static Map<PwmAboutProperty,String> makeInfoBean(
-            final PwmApplication pwmApplication
-    ) {
-        final Map<PwmAboutProperty,String> aboutMap = new TreeMap<>();
-
-        // about page
-        aboutMap.put(PwmAboutProperty.app_version,                  PwmConstants.SERVLET_VERSION);
-        aboutMap.put(PwmAboutProperty.app_currentTime,              dateFormatForInfoBean(new Date()));
-        aboutMap.put(PwmAboutProperty.app_startTime,                dateFormatForInfoBean(pwmApplication.getStartupTime()));
-        aboutMap.put(PwmAboutProperty.app_installTime,              dateFormatForInfoBean(pwmApplication.getInstallTime()));
-        aboutMap.put(PwmAboutProperty.app_siteUrl,                  pwmApplication.getConfig().readSettingAsString(PwmSetting.PWM_SITE_URL));
-        aboutMap.put(PwmAboutProperty.app_instanceID,               pwmApplication.getInstanceID());
-        aboutMap.put(PwmAboutProperty.app_chaiApiVersion,           PwmConstants.CHAI_API_VERSION);
-
-        if (pwmApplication.getConfig().readSettingAsBoolean(PwmSetting.VERSION_CHECK_ENABLE)) {
-            if (pwmApplication.getVersionChecker() != null) {
-                aboutMap.put(PwmAboutProperty.app_currentPublishedVersion, pwmApplication.getVersionChecker().currentVersion());
-                aboutMap.put(PwmAboutProperty.app_currentPublishedVersionCheckTime, dateFormatForInfoBean(pwmApplication.getVersionChecker().lastReadTimestamp()));
-            }
-        }
-
-        aboutMap.put(PwmAboutProperty.app_secureBlockAlgorithm,     pwmApplication.getSecureService().getDefaultBlockAlgorithm().getLabel());
-        aboutMap.put(PwmAboutProperty.app_secureHashAlgorithm,      pwmApplication.getSecureService().getDefaultHashAlgorithm().toString());
-
-        aboutMap.put(PwmAboutProperty.app_wordlistSize,             Integer.toString(pwmApplication.getWordlistManager().size()));
-        aboutMap.put(PwmAboutProperty.app_seedlistSize,             Integer.toString(pwmApplication.getSeedlistManager().size()));
-        if (pwmApplication.getSharedHistoryManager() != null) {
-            aboutMap.put(PwmAboutProperty.app_sharedHistorySize,    Integer.toString(pwmApplication.getSharedHistoryManager().size()));
-            aboutMap.put(PwmAboutProperty.app_sharedHistoryOldestTime, dateFormatForInfoBean(pwmApplication.getSharedHistoryManager().getOldestEntryTime()));
-        }
-
-
-        if (pwmApplication.getEmailQueue() != null) {
-            aboutMap.put(PwmAboutProperty.app_emailQueueSize,       Integer.toString(pwmApplication.getEmailQueue().queueSize()));
-            aboutMap.put(PwmAboutProperty.app_emailQueueOldestTime, dateFormatForInfoBean(pwmApplication.getEmailQueue().eldestItem()));
-        }
-
-        if (pwmApplication.getSmsQueue() != null) {
-            aboutMap.put(PwmAboutProperty.app_smsQueueSize,         Integer.toString(pwmApplication.getSmsQueue().queueSize()));
-            aboutMap.put(PwmAboutProperty.app_smsQueueOldestTime,   dateFormatForInfoBean(pwmApplication.getSmsQueue().eldestItem()));
-        }
-
-        if (pwmApplication.getAuditManager() != null) {
-            aboutMap.put(PwmAboutProperty.app_syslogQueueSize,      Integer.toString(pwmApplication.getAuditManager().syslogQueueSize()));
-        }
-
-        if (pwmApplication.getLocalDB() != null) {
-            aboutMap.put(PwmAboutProperty.app_localDbLogSize,       Integer.toString(pwmApplication.getLocalDBLogger().getStoredEventCount()));
-            aboutMap.put(PwmAboutProperty.app_localDbLogOldestTime, dateFormatForInfoBean(pwmApplication.getLocalDBLogger().getTailDate()));
-
-            aboutMap.put(PwmAboutProperty.app_localDbStorageSize,   formatDiskSize(FileSystemUtility.getFileDirectorySize(pwmApplication.getLocalDB().getFileLocation())));
-            aboutMap.put(PwmAboutProperty.app_localDbFreeSpace,     formatDiskSize(FileSystemUtility.diskSpaceRemaining(pwmApplication.getLocalDB().getFileLocation())));
-        }
-
-
-        { // java info
-            final Runtime runtime = Runtime.getRuntime();
-            aboutMap.put(PwmAboutProperty.java_memoryFree,          Long.toString(runtime.freeMemory()));
-            aboutMap.put(PwmAboutProperty.java_memoryAllocated,     Long.toString(runtime.totalMemory()));
-            aboutMap.put(PwmAboutProperty.java_memoryMax,           Long.toString(runtime.maxMemory()));
-            aboutMap.put(PwmAboutProperty.java_threadCount,         Integer.toString(Thread.activeCount()));
-
-            aboutMap.put(PwmAboutProperty.java_vmVendor,            System.getProperty("java.vm.vendor"));
-
-            aboutMap.put(PwmAboutProperty.java_runtimeVersion,      System.getProperty("java.runtime.version"));
-            aboutMap.put(PwmAboutProperty.java_vmVersion,           System.getProperty("java.vm.version"));
-            aboutMap.put(PwmAboutProperty.java_vmName,              System.getProperty("java.vm.name"));
-            aboutMap.put(PwmAboutProperty.java_vmLocation,          System.getProperty("java.home"));
-
-            aboutMap.put(PwmAboutProperty.java_osName,              System.getProperty("os.name"));
-            aboutMap.put(PwmAboutProperty.java_osVersion,           System.getProperty("os.version"));
-            aboutMap.put(PwmAboutProperty.java_randomAlgorithm,     PwmRandom.getInstance().getAlgorithm());
-        }
-
-        { // build info
-            aboutMap.put(PwmAboutProperty.build_Time,               PwmConstants.BUILD_TIME);
-            aboutMap.put(PwmAboutProperty.build_Number,             PwmConstants.BUILD_NUMBER);
-            aboutMap.put(PwmAboutProperty.build_Type,               PwmConstants.BUILD_TYPE);
-            aboutMap.put(PwmAboutProperty.build_User,               PwmConstants.BUILD_USER);
-            aboutMap.put(PwmAboutProperty.build_Revision,           PwmConstants.BUILD_REVISION);
-            aboutMap.put(PwmAboutProperty.build_JavaVendor,         PwmConstants.BUILD_JAVA_VENDOR);
-            aboutMap.put(PwmAboutProperty.build_JavaVersion,        PwmConstants.BUILD_JAVA_VERSION);
-            aboutMap.put(PwmAboutProperty.build_Version,            PwmConstants.BUILD_VERSION);
-        }
-
-        { // database info
-            try {
-                final DatabaseAccessor databaseAccessor = pwmApplication.getDatabaseAccessor();
-                if (databaseAccessor != null) {
-                    final Map<PwmAboutProperty,String> debugData = databaseAccessor.getConnectionDebugProperties();
-                    aboutMap.putAll(debugData);
-                }
-            } catch (Throwable t) {
-                LOGGER.error("error reading database debug properties");
-            }
-        }
-
-        return Collections.unmodifiableMap(aboutMap);
-    }
-
-    public static int portForUriSchema(final URI uri) {
-        final int port = uri.getPort();
-        if (port < 1) {
-            return portForUriScheme(uri.getScheme());
-        }
-        return port;
-    }
-
-    private static int portForUriScheme(final String scheme) {
-        if (scheme == null) {
-            throw new NullPointerException("scheme cannot be null");
-        }
-        switch (scheme) {
-            case "http": return 80;
-            case "https": return 443;
-            case "ldap": return 389;
-            case "ldaps": return 636;
-        }
-        throw new IllegalArgumentException("unknown scheme: " + scheme);
-    }
 
     public static <E extends Enum<E>> E readEnumFromString(Class<E> enumClass, E defaultValue, String input) {
         if (input == null) {

+ 2 - 1
src/main/java/password/pwm/util/X509Utils.java

@@ -28,6 +28,7 @@ import password.pwm.error.ErrorInformation;
 import password.pwm.error.PwmError;
 import password.pwm.error.PwmOperationalException;
 import password.pwm.error.PwmUnrecoverableException;
+import password.pwm.http.PwmURL;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.secure.PwmHashAlgorithm;
 import password.pwm.util.secure.SecureEngine;
@@ -47,7 +48,7 @@ public abstract class X509Utils {
             throws PwmOperationalException
     {
         final String host = uri.getHost();
-        final int port = Helper.portForUriSchema(uri);
+        final int port = PwmURL.portForUriSchema(uri);
 
         return readRemoteCertificates(host, port);
     }

+ 2 - 2
src/main/java/password/pwm/ws/client/rest/naaf/NAAFEndPoint.java

@@ -29,7 +29,7 @@ import password.pwm.config.Configuration;
 import password.pwm.config.PwmSetting;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.HttpMethod;
-import password.pwm.http.ServletHelper;
+import password.pwm.http.PwmURL;
 import password.pwm.http.client.PwmHttpClient;
 import password.pwm.http.client.PwmHttpClientConfiguration;
 import password.pwm.http.client.PwmHttpClientRequest;
@@ -125,7 +125,7 @@ public class NAAFEndPoint {
         urlParams.put("is_trusted", "true");
         urlParams.put("endpoint_session_id", this.getEndpoint_session_id());
 
-        final String url = ServletHelper.appendAndEncodeUrlParameters( "/logon/chains", urlParams );
+        final String url = PwmURL.appendAndEncodeUrlParameters("/logon/chains", urlParams);
 
         final PwmHttpClientResponse response = makeApiRequest(
                 HttpMethod.POST,

+ 0 - 7
src/main/java/password/pwm/ws/server/RestServerHelper.java

@@ -35,7 +35,6 @@ import password.pwm.error.PwmOperationalException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.PwmRequest;
 import password.pwm.http.PwmSession;
-import password.pwm.http.ServletHelper;
 import password.pwm.http.filter.AuthenticationFilter;
 import password.pwm.ldap.UserSearchEngine;
 import password.pwm.svc.intruder.RecordType;
@@ -72,12 +71,6 @@ public abstract class RestServerHelper {
         final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
         final PwmSession pwmSession = pwmRequest.getPwmSession();
 
-        ServletHelper.handleRequestInitialization(pwmRequest, pwmApplication, pwmSession);
-
-        if (servicePermissions.isAuthRequired()) {
-            ServletHelper.handleRequestSecurityChecks(request, pwmApplication, pwmSession);
-        }
-
         if (pwmSession.getSessionStateBean().getLocale() == null) {
             final List<Locale> knownLocales = pwmApplication.getConfig().getKnownLocales();
             final Locale userLocale = LocaleHelper.localeResolver(request.getLocale(), knownLocales);

+ 1 - 0
src/main/resources/password/pwm/AppProperty.properties

@@ -78,6 +78,7 @@ http.gzip.enable=true
 http.errors.allowHtml=true
 http.basicAuth.charset=UTF-8
 http.body.maxReadLength=10485760
+http.header.server=@PwmAppName@
 http.header.sendXAmb=true
 http.header.sendXInstance=true
 http.header.sendXNoise=true