Compare commits

...

11 commits
master ... v1_9

Author SHA1 Message Date
Jason Rivard
861f3487cd Merge remote-tracking branch 'origin/v1_9' into v1_9 2021-08-14 19:41:03 -04:00
Jason Rivard
1165cf6189 Merge branch 'v1_9' of https://github.com/pwm-project/pwm into v1_9
# Conflicts:
#	client/pom.xml
2021-08-14 19:40:50 -04:00
Jason Rivard
bd19e88364 Merge branch 'v1_9' of https://github.com/pwm-project/pwm into v1_9
# Conflicts:
#	client/pom.xml
2021-08-14 19:40:01 -04:00
Jason Rivard
e4c88cdcf6 bump version to 1.9.3-SNAPSHOT 2021-08-14 19:37:36 -04:00
Jason Rivard
de26a35223 bump version to 1.9.2 2021-08-14 19:09:15 -04:00
Jason Rivard
644a4221ec dependency updates 2021-08-14 18:50:55 -04:00
Jason Rivard
4355ed1729 dependency updates 2021-08-14 03:11:57 -04:00
Jason Rivard
7c929ac251 bump version to 1.9.2-SNAPSHOT 2021-08-13 19:59:47 -04:00
Jason Rivard
db1407912c fix spurious log messages in captcha and mbeans classes 2019-08-02 21:14:01 -04:00
Jason Rivard
21569ae1a2 update version to v1.9.1 2019-08-02 19:06:02 -04:00
Jason Rivard
ea2f4f1c14 config authentication improvements 2019-08-02 18:43:34 -04:00
35 changed files with 625 additions and 455 deletions

View file

@ -46,6 +46,12 @@
<property name="fileExtensions" value="jsp,java"/>
</module>
<module name="LineLength">
<property name="max" value="180" />
<property name="ignorePattern" value="@version|@see|@todo|TODO"/>
<property name="fileExtensions" value="java"/>
</module>
<!-- Checks for Headers -->
<!-- See http://checkstyle.sf.net/config_header.html -->
<!--
@ -80,11 +86,6 @@
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="LineLength">
<property name="max" value="180" />
<property name="ignorePattern" value="@version|@see|@todo|TODO"/>
</module>
<module name="EmptyBlock">
<property name="option" value="TEXT"/>
<property name="tokens" value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>

View file

@ -31,4 +31,7 @@
<!-- due to bug with java 11 -->
<Bug pattern="RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE"/>
</Match>
<Match>
<Bug pattern="DMI_RANDOM_USED_ONLY_ONCE"/>
</Match>
</FindBugsFilter>

View file

@ -8,27 +8,28 @@
"npm": ">=3.9"
},
"scripts": {
"build": "webpack --mode=production",
"build": "webpack --mode=development",
"clean": "rimraf dist/",
"test": "karma start test/karma.conf.js",
"test-single-run": "karma start test/karma.conf.js --singleRun --no-auto-watch",
"start": "webpack-dev-server --mode=development --port 4000 --history-api-fallback --colors"
"start": "webpack-dev-server --mode=development --port 4000 --history-api-fallback --colors --progress"
},
"author": "",
"license": "ISC",
"dependencies": {
"@microfocus/ias-icons": "1.0.1",
"@microfocus/ng-ias": "1.0.0-alpha.2",
"@microfocus/ux-ias": "1.0.0-rc",
"@microfocus/ias-icons": "1.0.4",
"@microfocus/ng-ias": "1.0.1",
"@microfocus/ux-ias": "1.1.2",
"@uirouter/angularjs": "1.0.15",
"angular": "1.6.9",
"angular-aria": "1.6.9",
"angular-sanitize": "1.6.9",
"angular-translate": "2.17.0",
"angular": "^1.7.9",
"angular-aria": "1.7.8",
"angular-sanitize": "1.7.9",
"angular-translate": "2.18.1",
"core-js": "3.5.0",
"textangular": "1.5.16"
},
"devDependencies": {
"@types/angular": "1.6.43",
"@types/angular": "^1.8.1",
"@types/angular-mocks": "1.5.11",
"@types/angular-translate": "2.15.2",
"@types/angular-ui-router": "1.1.40",
@ -36,8 +37,8 @@
"@types/node": "9.4.7",
"angular-mocks": "1.6.9",
"autoprefixer": "8.1.0",
"copy-webpack-plugin": "4.5.1",
"css-loader": "0.28.10",
"copy-webpack-plugin": "^5.1.1",
"css-loader": "^3.3.2",
"file-loader": "1.1.11",
"html-loader": "0.5.5",
"html-webpack-plugin": "3.0.6",
@ -45,10 +46,10 @@
"imports-loader": "0.8.0",
"jasmine": "3.2.0",
"jasmine-core": "3.2.1",
"jshint": "2.9.5",
"jshint": "^2.13.0",
"jshint-loader": "0.8.4",
"json-loader": "0.5.7",
"karma": "3.1.1",
"karma": "^4.4.1",
"karma-chrome-launcher": "2.2.0",
"karma-jasmine": "1.1.2",
"karma-jasmine-html-reporter": "1.3.1",
@ -58,7 +59,7 @@
"karma-webpack": "3.0.5",
"moment": "2.21.0",
"ngtemplate-loader": "2.0.1",
"node-sass": "4.7.2",
"node-sass": "^6.0.1",
"phantomjs": "2.1.7",
"phantomjs-prebuilt": "2.1.16",
"postcss-loader": "2.1.1",
@ -67,6 +68,7 @@
"sass-loader": "6.0.7",
"string-replace-loader": "2.1.1",
"style-loader": "0.20.3",
"trim-newlines": ">=3.0.1",
"ts-loader": "4.0.1",
"ts-mockito": "2.3.1",
"tslint": "5.9.1",
@ -74,8 +76,8 @@
"typescript": "2.7.2",
"uglifyjs-webpack-plugin": "1.2.3",
"url-loader": "1.0.1",
"webpack": "4.1.1",
"webpack-cli": "2.0.12",
"webpack": "^4.46.0",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "3.1.14",
"webpack-merge": "4.1.2",
"write-file-webpack-plugin": "4.2.0"

View file

@ -3,7 +3,7 @@
<parent>
<groupId>org.pwm-project</groupId>
<artifactId>pwm-parent</artifactId>
<version>1.9.0</version>
<version>1.9.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -16,6 +16,8 @@
<properties>
<project.root.basedir>${project.basedir}/..</project.root.basedir>
<node.version>v14.17.2</node.version>
<npm.version>6.14.13</npm.version>
</properties>
<profiles>
@ -79,11 +81,11 @@
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.7.6</version>
<version>1.12.0</version>
<configuration>
<nodeVersion>v8.9.4</nodeVersion>
<npmVersion>5.6.0</npmVersion>
<installDirectory>.node</installDirectory>
<nodeVersion>${node.version}</nodeVersion>
<npmVersion>${npm.version}</npmVersion>
<installDirectory>${settings.localRepository}/frontend-maven-plugin/node-${node.version}</installDirectory>
</configuration>
<executions>
<execution>
@ -115,7 +117,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<version>3.2.0</version>
<configuration>
<archive>
<manifestEntries>

View file

@ -24,7 +24,7 @@ import 'angular-sanitize';
import '@microfocus/ng-ias/dist/ng-ias';
// Add a polyfill for Set() for IE11, since it's used in peoplesearch-base.component.ts
import 'core-js/es6/set';
import 'core-js/es/set';
import { bootstrap, module } from 'angular';
import helpDeskModule from './helpdesk.module';

View file

@ -23,7 +23,7 @@ import 'angular-translate';
import '@microfocus/ng-ias/dist/ng-ias';
// Add a polyfill for Set() for IE11, since it's used in peoplesearch-base.component.ts
import 'core-js/es6/set';
import 'core-js/es/set';
import { bootstrap, module } from 'angular';
import ConfigService from '../../services/peoplesearch-config.service';

View file

@ -3,7 +3,7 @@
<parent>
<groupId>org.pwm-project</groupId>
<artifactId>pwm-parent</artifactId>
<version>1.9.0</version>
<version>1.9.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -122,17 +122,17 @@
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
<version>3.8.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.7</version>
<version>1.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
@ -142,7 +142,7 @@
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.9</version>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
@ -157,12 +157,12 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
<version>2.8.7</version>
</dependency>
<dependency>
<groupId>org.jetbrains.xodus</groupId>
<artifactId>xodus-environment</artifactId>
<version>1.3.0</version>
<version>1.3.232</version>
</dependency>
</dependencies>
</project>

View file

@ -3,7 +3,7 @@
<parent>
<groupId>org.pwm-project</groupId>
<artifactId>pwm-parent</artifactId>
<version>1.9.0</version>
<version>1.9.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -34,7 +34,7 @@
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>1.2.0</version>
<version>3.1.2</version>
<executions>
<execution>
<id>make-docker-image</id>
@ -44,10 +44,12 @@
</goals>
<configuration>
<skip>${skipDocker}</skip>
<jib.console>plain</jib.console>
<from>
<image>adoptopenjdk/openjdk11:jre</image>
</from>
<outputPaths>
<tar>target/pwm-docker-image-${project.version}.tar</tar>
</outputPaths>
<to>
<image>${dockerImageTag}</image>
</to>
@ -55,14 +57,17 @@
<entrypoint>
<arg>/app/startup.sh</arg>
</entrypoint>
<format>docker</format>
<ports>8443</ports>
<ports>
<port>8443</port>
</ports>
<volumes>
<volume>/config</volume>
</volumes>
</container>
<extraDirectory>
<path>${project.basedir}/src/main/image-files</path>
<extraDirectories>
<paths>
<path>${project.basedir}/src/main/image-files</path>
</paths>
<permissions>
<permission>
<file>/app/startup.sh</file>
@ -73,7 +78,7 @@
<mode>755</mode>
</permission>
</permissions>
</extraDirectory>
</extraDirectories>
</configuration>
</execution>
</executions>

View file

@ -3,7 +3,7 @@
<parent>
<groupId>org.pwm-project</groupId>
<artifactId>pwm-parent</artifactId>
<version>1.9.0</version>
<version>1.9.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -17,7 +17,7 @@
<properties>
<project.root.basedir>${project.basedir}/..</project.root.basedir>
<tomcat.version>9.0.21</tomcat.version>
<tomcat.version>9.0.52</tomcat.version>
</properties>
<build>
@ -26,7 +26,7 @@
<!-- prevent normal jar from being built -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<version>3.2.0</version>
<executions>
<execution>
<id>default-jar</id>

34
pom.xml
View file

@ -4,7 +4,7 @@
<groupId>org.pwm-project</groupId>
<artifactId>pwm-parent</artifactId>
<version>1.9.0</version>
<version>1.9.3-SNAPSHOT</version>
<packaging>pom</packaging>
<name>PWM Password Self Service</name>
@ -167,12 +167,12 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.0</version>
<version>3.1.2</version>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>8.21</version>
<version>8.45.1</version>
</dependency>
</dependencies>
<executions>
@ -242,12 +242,12 @@
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>3.1.11</version>
<version>4.2.3</version>
<dependencies>
<dependency>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs</artifactId>
<version>4.0.0-beta2</version>
<version>4.2.3</version>
</dependency>
</dependencies>
<configuration>
@ -268,7 +268,7 @@
<plugin> <!-- checks owsp vulnerability database -->
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>5.0.0-M3</version>
<version>6.2.2</version>
<executions>
<execution>
<goals>
@ -276,6 +276,10 @@
</goals>
</execution>
</executions>
<configuration>
<yarnAuditAnalyzerEnabled>false</yarnAuditAnalyzerEnabled>
<nodeAnalyzerEnabled>false</nodeAnalyzerEnabled>
</configuration>
</plugin>
</plugins>
</build>
@ -285,13 +289,13 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-annotations</artifactId>
<version>4.0.0-beta2</version>
<version>4.3.0</version>
<scope>provided</scope>
</dependency>
@ -299,43 +303,43 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.28.2</version>
<version>3.11.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.12.2</version>
<version>3.20.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>2.23.2</version>
<version>2.27.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.11</version>
<version>0.9.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.21</version>
<version>1.33</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.21</version>
<version>1.33</version>
<scope>test</scope>
</dependency>

View file

@ -4,7 +4,7 @@
<parent>
<groupId>org.pwm-project</groupId>
<artifactId>pwm-parent</artifactId>
<version>1.9.0</version>
<version>1.9.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -25,7 +25,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
<version>2.8.7</version>
</dependency>
<dependency>
<groupId>org.jdom</groupId>
@ -45,14 +45,14 @@
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.62</version>
<version>1.69</version>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
@ -72,7 +72,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<version>3.2.0</version>
<configuration>
<archive>
<manifestEntries>

View file

@ -3,7 +3,7 @@
<parent>
<groupId>org.pwm-project</groupId>
<artifactId>pwm-parent</artifactId>
<version>1.9.0</version>
<version>1.9.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -78,7 +78,7 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
<version>2.8.7</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>

View file

@ -3,7 +3,7 @@
<parent>
<groupId>org.pwm-project</groupId>
<artifactId>pwm-parent</artifactId>
<version>1.9.0</version>
<version>1.9.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -105,7 +105,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<version>3.2.0</version>
<configuration>
<archive>
<manifestEntries>
@ -192,22 +192,22 @@
<dependency>
<groupId>com.github.ldapchai</groupId>
<artifactId>ldapchai</artifactId>
<version>0.7.5</version>
<version>0.8.1</version>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
<version>3.8.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.6</version>
<version>1.9</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.7</version>
<version>1.9.0</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
@ -217,12 +217,12 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.6</version>
<version>1.7</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
@ -232,7 +232,7 @@
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.9</version>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>org.graylog2</groupId>
@ -247,7 +247,7 @@
<dependency>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-core</artifactId>
<version>3.5.1</version>
<version>3.6.2</version>
</dependency>
<dependency>
<groupId>net.glxn</groupId>
@ -257,12 +257,12 @@
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.62</version>
<version>1.69</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.62</version>
<version>1.69</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
@ -287,17 +287,17 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
<version>2.8.7</version>
</dependency>
<dependency>
<groupId>com.blueconic</groupId>
<artifactId>browscap-java</artifactId>
<version>1.2.9</version>
<version>1.3.6</version>
</dependency>
<dependency>
<groupId>org.jetbrains.xodus</groupId>
<artifactId>xodus-environment</artifactId>
<version>1.3.0</version>
<version>1.3.232</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
@ -307,17 +307,17 @@
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
<version>0.37</version>
<version>0.47</version>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.7.0</version>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>com.nulab-inc</groupId>
<artifactId>zxcvbn</artifactId>
<version>1.2.5</version>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>com.github.ziplet</groupId>

View file

@ -217,6 +217,7 @@ public abstract class PwmConstants
"Your password must be scanned by the TSA to ensure the safety of your fellow travelers. Please take off your password's shoes to continue.",
"That password really tied the room together dude.",
"Bite my shiny metal password!",
"ben makes password software go woooo",
//nick helm
"I needed a password eight characters long so I picked Snow White and the Seven Dwarves.",

View file

@ -39,24 +39,6 @@ public class CrChallengeItemBean implements Serializable, Challenge
private int maxQuestionCharsInAnswer;
private boolean enforceWordlist;
@Override
public boolean isLocked()
{
return true;
}
@Override
public void lock()
{
}
@Override
public void setChallengeText( final String challengeText )
{
throw new IllegalStateException();
}
@Override
public ChallengeBean asChallengeBean()
{

View file

@ -96,17 +96,6 @@ public class CrChallengePolicyBean implements Serializable, ChallengeSet
return mininimumResponses;
}
@Override
public boolean isLocked()
{
return true;
}
@Override
public void lock()
{
}
@Override
public String getIdentifier()

View file

@ -34,6 +34,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;
public class PwmURL
@ -48,7 +49,8 @@ public class PwmURL
final String contextPath
)
{
this.uri = uri;
Objects.requireNonNull( uri );
this.uri = uri.normalize();
this.contextPath = contextPath;
}

View file

@ -20,58 +20,34 @@
package password.pwm.http.filter;
import com.google.gson.annotations.SerializedName;
import lombok.Value;
import password.pwm.AppProperty;
import password.pwm.Permission;
import password.pwm.PwmApplication;
import password.pwm.PwmApplicationMode;
import password.pwm.PwmConstants;
import password.pwm.bean.UserIdentity;
import password.pwm.config.PwmSetting;
import password.pwm.config.stored.ConfigurationProperty;
import password.pwm.config.stored.ConfigurationReader;
import password.pwm.config.stored.StoredConfiguration;
import password.pwm.config.stored.StoredConfigurationImpl;
import password.pwm.error.ErrorInformation;
import password.pwm.error.PwmError;
import password.pwm.error.PwmException;
import password.pwm.error.PwmUnrecoverableException;
import password.pwm.http.ContextManager;
import password.pwm.http.JspUrl;
import password.pwm.http.ProcessStatus;
import password.pwm.http.PwmHttpResponseWrapper;
import password.pwm.http.PwmRequest;
import password.pwm.http.PwmRequestAttribute;
import password.pwm.http.PwmSession;
import password.pwm.http.PwmURL;
import password.pwm.http.bean.ConfigManagerBean;
import password.pwm.svc.intruder.RecordType;
import password.pwm.http.servlet.PwmServletDefinition;
import password.pwm.svc.sessiontrack.UserAgentUtils;
import password.pwm.util.java.JavaHelper;
import password.pwm.util.java.StringUtil;
import password.pwm.util.java.TimeDuration;
import password.pwm.util.logging.PwmLogger;
import password.pwm.util.secure.PwmHashAlgorithm;
import password.pwm.util.secure.SecureEngine;
import javax.servlet.ServletException;
import java.io.IOException;
import java.io.Serializable;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ConfigAccessFilter extends AbstractPwmFilter
{
private static final PwmLogger LOGGER = PwmLogger.forClass( ConfigAccessFilter.class );
private static final String COOKIE_NAME = PwmConstants.COOKIE_PERSISTENT_CONFIG_LOGIN;
private static final PwmHttpResponseWrapper.CookiePath COOKIE_PATH = PwmHttpResponseWrapper.CookiePath.Private;
@Override
void processFilter( final PwmApplicationMode mode, final PwmRequest pwmRequest, final PwmFilterChain filterChain ) throws PwmException, IOException, ServletException
void processFilter( final PwmApplicationMode mode, final PwmRequest pwmRequest, final PwmFilterChain filterChain )
throws PwmException, IOException, ServletException
{
final PwmApplicationMode appMode = pwmRequest.getPwmApplication().getApplicationMode();
if ( appMode == PwmApplicationMode.NEW )
@ -111,17 +87,15 @@ public class ConfigAccessFilter extends AbstractPwmFilter
@Override
boolean isInterested( final PwmApplicationMode mode, final PwmURL pwmURL )
{
return pwmURL.isConfigManagerURL();
return true;
}
private static ProcessStatus checkAuthentication(
public static ProcessStatus checkAuthentication(
final PwmRequest pwmRequest,
final ConfigManagerBean configManagerBean
)
throws IOException, PwmUnrecoverableException, ServletException
{
final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
final PwmSession pwmSession = pwmRequest.getPwmSession();
final ConfigurationReader runningConfigReader = ContextManager.getContextManager( pwmRequest.getHttpServletRequest().getSession() ).getConfigReader();
final StoredConfigurationImpl storedConfig = runningConfigReader.getStoredConfiguration();
@ -132,117 +106,15 @@ public class ConfigAccessFilter extends AbstractPwmFilter
return ProcessStatus.Continue;
}
final boolean persistentLoginEnabled = persistentLoginEnabled( pwmRequest );
if ( persistentLoginEnabled )
if ( !pwmRequest.getURL().isPwmServletURL( PwmServletDefinition.ConfigManager_Login ) )
{
final boolean persistentLoginPassed = checkPersistentLoginCookie( pwmRequest, storedConfig );
if ( persistentLoginPassed )
{
return processLoginSuccess( pwmRequest, persistentLoginEnabled );
}
configManagerBean.setPrePasswordEntryUrl( pwmRequest.getHttpServletRequest().getRequestURL().toString() );
pwmRequest.sendRedirect( PwmServletDefinition.ConfigManager_Login );
return ProcessStatus.Halt;
}
final String password = pwmRequest.readParameterAsString( "password" );
boolean passwordAccepted = false;
if ( !StringUtil.isEmpty( password ) )
{
if ( storedConfig.verifyPassword( password, pwmRequest.getConfig() ) )
{
passwordAccepted = true;
LOGGER.trace( pwmRequest, () -> "valid configuration password accepted" );
updateLoginHistory( pwmRequest, pwmRequest.getUserInfoIfLoggedIn(), true );
}
else
{
LOGGER.trace( pwmRequest, () -> "configuration password is not correct" );
pwmApplication.getIntruderManager().convenience().markAddressAndSession( pwmSession );
pwmApplication.getIntruderManager().mark( RecordType.USERNAME, PwmConstants.CONFIGMANAGER_INTRUDER_USERNAME, pwmSession.getLabel() );
final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_PASSWORD_ONLY_BAD );
updateLoginHistory( pwmRequest, pwmRequest.getUserInfoIfLoggedIn(), false );
return denyAndError( pwmRequest, errorInformation );
}
}
if ( passwordAccepted )
{
return processLoginSuccess( pwmRequest, persistentLoginEnabled );
}
configManagerBean.setPrePasswordEntryUrl( pwmRequest.getHttpServletRequest().getRequestURL().toString() );
forwardToJsp( pwmRequest );
return ProcessStatus.Halt;
return ProcessStatus.Continue;
}
private static void writePersistentLoginCookie( final PwmRequest pwmRequest )
throws PwmUnrecoverableException
{
final int persistentSeconds = figureMaxLoginSeconds( pwmRequest );
if ( persistentSeconds > 0 )
{
final TimeDuration persistenceDuration = TimeDuration.of( persistentSeconds, TimeDuration.Unit.SECONDS );
final Instant expirationDate = persistenceDuration.incrementFromInstant( Instant.now() );
final StoredConfigurationImpl storedConfig = pwmRequest.getConfig().getStoredConfiguration();
final String persistentLoginValue = makePersistentLoginPassword( pwmRequest, storedConfig );
final PersistentLoginInfo persistentLoginInfo = new PersistentLoginInfo( expirationDate, persistentLoginValue );
final String cookieValue = pwmRequest.getPwmApplication().getSecureService().encryptObjectToString( persistentLoginInfo );
pwmRequest.getPwmResponse().writeCookie(
COOKIE_NAME,
cookieValue,
persistentSeconds,
COOKIE_PATH
);
LOGGER.debug( pwmRequest, () -> "set persistent config login cookie (expires "
+ JavaHelper.toIsoDate( expirationDate )
+ ")"
);
}
}
private static boolean checkPersistentLoginCookie(
final PwmRequest pwmRequest,
final StoredConfiguration storedConfig
)
{
try
{
final String cookieValue = pwmRequest.readCookie( COOKIE_NAME );
if ( !StringUtil.isEmpty( cookieValue ) )
{
final PersistentLoginInfo persistentLoginInfo = pwmRequest.getPwmApplication().getSecureService().decryptObject( cookieValue, PersistentLoginInfo.class );
if ( persistentLoginInfo != null )
{
if ( persistentLoginInfo.getExpireDate().isAfter( Instant.now() ) )
{
final String persistentLoginPassword = makePersistentLoginPassword( pwmRequest, storedConfig );
if ( StringUtil.nullSafeEquals( persistentLoginPassword, persistentLoginInfo.getPassword() ) )
{
LOGGER.debug( pwmRequest, () -> "accepting persistent config login from cookie (expires "
+ JavaHelper.toIsoDate( persistentLoginInfo.getExpireDate() )
+ ")"
);
return true;
}
}
pwmRequest.getPwmResponse().removeCookie( COOKIE_NAME, COOKIE_PATH );
LOGGER.debug( pwmRequest, () -> "removing non-working persistent config login cookie" );
}
}
}
catch ( Exception e )
{
LOGGER.error( pwmRequest, "error examining persistent config login cookie: " + e.getMessage() );
}
return false;
}
private static void checkPreconditions(
final PwmRequest pwmRequest,
final StoredConfigurationImpl storedConfig
@ -272,164 +144,6 @@ public class ConfigAccessFilter extends AbstractPwmFilter
{
throw new PwmUnrecoverableException( PwmError.ERROR_UNAUTHORIZED );
}
}
}
private static boolean persistentLoginEnabled(
final PwmRequest pwmRequest
)
{
if ( pwmRequest.getConfig().isDefaultValue( PwmSetting.PWM_SECURITY_KEY ) )
{
LOGGER.debug( pwmRequest, () -> "security not available, persistent login not possible." );
return false;
}
return true;
}
private static String makePersistentLoginPassword(
final PwmRequest pwmRequest,
final StoredConfiguration storedConfig
)
throws PwmUnrecoverableException
{
final int hashChars = 32;
String hashValue = storedConfig.readConfigProperty( ConfigurationProperty.PASSWORD_HASH );
if ( PwmApplicationMode.RUNNING == pwmRequest.getPwmApplication().getApplicationMode() )
{
final PwmSession pwmSession = pwmRequest.getPwmSession();
hashValue += pwmSession.getUserInfo().getUserIdentity().toDelimitedKey();
}
return StringUtil.truncate( SecureEngine.hash( hashValue, PwmHashAlgorithm.SHA512 ), hashChars );
}
private static void forwardToJsp( final PwmRequest pwmRequest )
throws ServletException, PwmUnrecoverableException, IOException
{
final int persistentSeconds = figureMaxLoginSeconds( pwmRequest );
final String time = TimeDuration.of( persistentSeconds, TimeDuration.Unit.SECONDS ).asLongString( pwmRequest.getLocale() );
final ConfigLoginHistory configLoginHistory = readConfigLoginHistory( pwmRequest );
pwmRequest.setAttribute( PwmRequestAttribute.ConfigLoginHistory, configLoginHistory );
pwmRequest.setAttribute( PwmRequestAttribute.ConfigPasswordRememberTime, time );
pwmRequest.forwardToJsp( JspUrl.CONFIG_MANAGER_LOGIN );
}
private static ConfigLoginHistory readConfigLoginHistory( final PwmRequest pwmRequest )
{
final ConfigLoginHistory configLoginHistory = pwmRequest.getPwmApplication().readAppAttribute( PwmApplication.AppAttribute.CONFIG_LOGIN_HISTORY, ConfigLoginHistory.class );
return configLoginHistory == null
? new ConfigLoginHistory()
: configLoginHistory;
}
private static void updateLoginHistory( final PwmRequest pwmRequest, final UserIdentity userIdentity, final boolean successful )
{
final ConfigLoginHistory configLoginHistory = readConfigLoginHistory( pwmRequest );
final ConfigLoginEvent event = new ConfigLoginEvent(
userIdentity == null ? "n/a" : userIdentity.toDisplayString(),
Instant.now(),
pwmRequest.getPwmSession().getSessionStateBean().getSrcAddress()
);
final int maxEvents = Integer.parseInt( pwmRequest.getPwmApplication().getConfig().readAppProperty( AppProperty.CONFIG_HISTORY_MAX_ITEMS ) );
configLoginHistory.addEvent( event, maxEvents, successful );
pwmRequest.getPwmApplication().writeAppAttribute( PwmApplication.AppAttribute.CONFIG_LOGIN_HISTORY, configLoginHistory );
}
@Value
private static class PersistentLoginInfo implements Serializable
{
@SerializedName( "e" )
private Instant expireDate;
@SerializedName( "p" )
private String password;
}
@Value
public static class ConfigLoginHistory implements Serializable
{
private List<ConfigLoginEvent> successEvents = new ArrayList<>();
private List<ConfigLoginEvent> failedEvents = new ArrayList<>();
void addEvent( final ConfigLoginEvent event, final int maxEvents, final boolean successful )
{
final List<ConfigLoginEvent> events = successful ? successEvents : failedEvents;
events.add( event );
if ( maxEvents > 0 )
{
while ( events.size() > maxEvents )
{
events.remove( 0 );
}
}
}
public List<ConfigLoginEvent> successEvents( )
{
return Collections.unmodifiableList( successEvents );
}
public List<ConfigLoginEvent> failedEvents( )
{
return Collections.unmodifiableList( failedEvents );
}
}
@Value
public static class ConfigLoginEvent implements Serializable
{
private final String userIdentity;
private final Instant date;
private final String networkAddress;
}
private static int figureMaxLoginSeconds( final PwmRequest pwmRequest )
{
return JavaHelper.silentParseInt(
pwmRequest.getConfig().readAppProperty( AppProperty.CONFIG_MAX_PERSISTENT_LOGIN_SECONDS ),
(int) TimeDuration.HOUR.as( TimeDuration.Unit.SECONDS )
);
}
private static ProcessStatus denyAndError( final PwmRequest pwmRequest, final ErrorInformation errorInformation )
throws ServletException, PwmUnrecoverableException, IOException
{
pwmRequest.respondWithError( errorInformation );
return ProcessStatus.Halt;
}
private static ProcessStatus processLoginSuccess( final PwmRequest pwmRequest, final boolean persistentLoginEnabled )
throws PwmUnrecoverableException, IOException
{
final ConfigManagerBean configManagerBean = pwmRequest.getPwmApplication().getSessionStateService().getBean( pwmRequest, ConfigManagerBean.class );
final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
final PwmSession pwmSession = pwmRequest.getPwmSession();
configManagerBean.setPasswordVerified( true );
pwmApplication.getIntruderManager().convenience().clearAddressAndSession( pwmSession );
pwmApplication.getIntruderManager().clear( RecordType.USERNAME, PwmConstants.CONFIGMANAGER_INTRUDER_USERNAME );
pwmRequest.getPwmSession().getSessionStateBean().setSessionIdRecycleNeeded( true );
if ( persistentLoginEnabled && "on".equals( pwmRequest.readParameterAsString( "remember" ) ) )
{
writePersistentLoginCookie( pwmRequest );
}
if ( configManagerBean.getPrePasswordEntryUrl() != null )
{
final String originalUrl = configManagerBean.getPrePasswordEntryUrl();
configManagerBean.setPrePasswordEntryUrl( null );
pwmRequest.getPwmResponse().sendRedirect( originalUrl );
return ProcessStatus.Halt;
}
pwmRequest.sendRedirect( pwmRequest.getURLwithQueryString() );
return ProcessStatus.Continue;
}
}

View file

@ -48,6 +48,7 @@ import password.pwm.http.servlet.configeditor.ConfigEditorServlet;
import password.pwm.http.servlet.configguide.ConfigGuideServlet;
import password.pwm.http.servlet.configmanager.ConfigManagerCertificatesServlet;
import password.pwm.http.servlet.configmanager.ConfigManagerLocalDBServlet;
import password.pwm.http.servlet.configmanager.ConfigManagerLoginServlet;
import password.pwm.http.servlet.configmanager.ConfigManagerServlet;
import password.pwm.http.servlet.configmanager.ConfigManagerWordlistServlet;
import password.pwm.http.servlet.newuser.NewUserServlet;
@ -90,6 +91,7 @@ public enum PwmServletDefinition
ConfigGuide( ConfigGuideServlet.class, ConfigGuideBean.class ),
ConfigEditor( ConfigEditorServlet.class, null ),
ConfigManager( ConfigManagerServlet.class, ConfigManagerBean.class ),
ConfigManager_Login( ConfigManagerLoginServlet.class, ConfigManagerBean.class ),
ConfigManager_Wordlists( ConfigManagerWordlistServlet.class, ConfigManagerBean.class ),
ConfigManager_LocalDB( ConfigManagerLocalDBServlet.class, ConfigManagerBean.class ),
ConfigManager_Certificates( ConfigManagerCertificatesServlet.class, ConfigManagerBean.class ),

View file

@ -21,6 +21,7 @@
package password.pwm.http.servlet;
import com.novell.ldapchai.ChaiUser;
import com.novell.ldapchai.cr.ChaiChallenge;
import com.novell.ldapchai.cr.ChaiCrFactory;
import com.novell.ldapchai.cr.ChaiResponseSet;
import com.novell.ldapchai.cr.Challenge;
@ -475,18 +476,30 @@ public class SetupResponsesServlet extends ControlledPwmServlet
final Challenge loopChallenge = setupData.getIndexedChallenges().get( indexKey );
if ( loopChallenge.isRequired() || !setupData.isSimpleMode() )
{
final Challenge newChallenge;
if ( !loopChallenge.isAdminDefined() )
{
final String questionText = inputMap.get( PwmConstants.PARAM_QUESTION_PREFIX + indexKey );
loopChallenge.setChallengeText( questionText );
newChallenge = new ChaiChallenge(
loopChallenge.isRequired(),
questionText,
loopChallenge.getMinLength(),
loopChallenge.getMaxLength(),
loopChallenge.isAdminDefined(),
loopChallenge.getMaxQuestionCharsInAnswer(),
loopChallenge.isEnforceWordlist()
);
}
else
{
newChallenge = loopChallenge;
}
final String answer = inputMap.get( PwmConstants.PARAM_RESPONSE_PREFIX + indexKey );
if ( answer != null && answer.length() > 0 )
{
readResponses.put( loopChallenge, answer );
readResponses.put( newChallenge, answer );
}
}
}

View file

@ -72,12 +72,12 @@ import password.pwm.i18n.Message;
import password.pwm.i18n.PwmLocaleBundle;
import password.pwm.ldap.LdapBrowser;
import password.pwm.util.PasswordData;
import password.pwm.util.password.RandomPasswordGenerator;
import password.pwm.util.java.JsonUtil;
import password.pwm.util.java.StringUtil;
import password.pwm.util.java.TimeDuration;
import password.pwm.util.logging.PwmLogger;
import password.pwm.util.macro.MacroMachine;
import password.pwm.util.password.RandomPasswordGenerator;
import password.pwm.util.queue.SmsQueueManager;
import password.pwm.util.secure.HttpsServerCertificateManager;
import password.pwm.ws.server.RestResultBean;
@ -164,8 +164,11 @@ public class ConfigEditorServlet extends ControlledPwmServlet
}
@Override
public ProcessStatus preProcessCheck( final PwmRequest pwmRequest ) throws PwmUnrecoverableException, IOException, ServletException
public ProcessStatus preProcessCheck( final PwmRequest pwmRequest )
throws PwmUnrecoverableException, IOException, ServletException
{
ConfigManagerServlet.verifyConfigAccess( pwmRequest );
final ConfigManagerBean configManagerBean = getBean( pwmRequest );
if ( configManagerBean.getStoredConfiguration() == null )

View file

@ -98,6 +98,8 @@ public class ConfigManagerCertificatesServlet extends AbstractPwmServlet
protected void processAction( final PwmRequest pwmRequest )
throws ServletException, IOException, ChaiUnavailableException, PwmUnrecoverableException
{
ConfigManagerServlet.verifyConfigAccess( pwmRequest );
final ConfigManagerCertificateAction action = readProcessAction( pwmRequest );
final ArrayList<CertificateDebugDataItem> certificateDebugDataItems = new ArrayList<>( makeCertificateDebugData( pwmRequest.getConfig() ) );

View file

@ -20,7 +20,6 @@
package password.pwm.http.servlet.configmanager;
import com.novell.ldapchai.exception.ChaiUnavailableException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import password.pwm.AppProperty;
import password.pwm.PwmApplication;
@ -103,8 +102,9 @@ public class ConfigManagerLocalDBServlet extends AbstractPwmServlet
}
protected void processAction( final PwmRequest pwmRequest )
throws ServletException, IOException, ChaiUnavailableException, PwmUnrecoverableException
throws ServletException, IOException, PwmUnrecoverableException
{
ConfigManagerServlet.verifyConfigAccess( pwmRequest );
final ConfigManagerAction processAction = readProcessAction( pwmRequest );
if ( processAction != null )

View file

@ -0,0 +1,420 @@
/*
* Password Management Servlets (PWM)
* http://www.pwm-project.org
*
* Copyright (c) 2006-2009 Novell, Inc.
* Copyright (c) 2009-2019 The PWM Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package password.pwm.http.servlet.configmanager;
import com.google.gson.annotations.SerializedName;
import com.novell.ldapchai.exception.ChaiUnavailableException;
import lombok.Value;
import password.pwm.AppProperty;
import password.pwm.PwmApplication;
import password.pwm.PwmApplicationMode;
import password.pwm.PwmConstants;
import password.pwm.bean.UserIdentity;
import password.pwm.config.PwmSetting;
import password.pwm.config.stored.ConfigurationProperty;
import password.pwm.config.stored.ConfigurationReader;
import password.pwm.config.stored.StoredConfiguration;
import password.pwm.config.stored.StoredConfigurationImpl;
import password.pwm.error.ErrorInformation;
import password.pwm.error.PwmError;
import password.pwm.error.PwmUnrecoverableException;
import password.pwm.http.ContextManager;
import password.pwm.http.HttpMethod;
import password.pwm.http.JspUrl;
import password.pwm.http.ProcessStatus;
import password.pwm.http.PwmHttpResponseWrapper;
import password.pwm.http.PwmRequest;
import password.pwm.http.PwmRequestAttribute;
import password.pwm.http.PwmSession;
import password.pwm.http.bean.ConfigManagerBean;
import password.pwm.http.servlet.AbstractPwmServlet;
import password.pwm.http.servlet.PwmServletDefinition;
import password.pwm.svc.intruder.RecordType;
import password.pwm.util.java.JavaHelper;
import password.pwm.util.java.StringUtil;
import password.pwm.util.java.TimeDuration;
import password.pwm.util.logging.PwmLogger;
import password.pwm.util.secure.PwmHashAlgorithm;
import password.pwm.util.secure.SecureEngine;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
import java.io.Serializable;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@WebServlet(
name = "ConfigManagerLogin",
urlPatterns = {
PwmConstants.URL_PREFIX_PRIVATE + "/config/login",
}
)
public class ConfigManagerLoginServlet extends AbstractPwmServlet
{
private static final PwmLogger LOGGER = PwmLogger.forClass( ConfigManagerLoginServlet.class );
private static final String COOKIE_NAME = PwmConstants.COOKIE_PERSISTENT_CONFIG_LOGIN;
private static final PwmHttpResponseWrapper.CookiePath COOKIE_PATH = PwmHttpResponseWrapper.CookiePath.CurrentURL;
public enum ConfigManagerLoginAction implements ProcessAction
{
login( HttpMethod.POST ),;
private final HttpMethod method;
ConfigManagerLoginAction( final HttpMethod method )
{
this.method = method;
}
public Collection<HttpMethod> permittedMethods( )
{
return Collections.singletonList( method );
}
}
@Override
protected void processAction( final PwmRequest pwmRequest )
throws ServletException, IOException, ChaiUnavailableException, PwmUnrecoverableException
{
checkPersistentLoginCookie( pwmRequest );
final ConfigManagerLoginAction processAction = readProcessAction( pwmRequest );
if ( processAction != null )
{
switch ( processAction )
{
case login:
processLoginRequest( pwmRequest );
break;
default:
JavaHelper.unhandledSwitchStatement( processAction );
}
return;
}
final ConfigManagerBean configManagerBean = pwmRequest.getPwmApplication().getSessionStateService().getBean( pwmRequest, ConfigManagerBean.class );
if ( configManagerBean.isPasswordVerified() )
{
forwardToNextUrl( pwmRequest );
return;
}
forwardToJsp( pwmRequest );
}
protected void processLoginRequest( final PwmRequest pwmRequest )
throws PwmUnrecoverableException, IOException, ServletException
{
final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
final ConfigurationReader runningConfigReader = ContextManager.getContextManager( pwmRequest.getHttpServletRequest().getSession() ).getConfigReader();
final StoredConfigurationImpl storedConfig = runningConfigReader.getStoredConfiguration();
final String password = pwmRequest.readParameterAsString( "password" );
if ( !StringUtil.isEmpty( password ) )
{
if ( storedConfig.verifyPassword( password, pwmRequest.getConfig() ) )
{
LOGGER.trace( pwmRequest, () -> "valid configuration password accepted" );
updateLoginHistory( pwmRequest, pwmRequest.getUserInfoIfLoggedIn(), true );
processLoginSuccess( pwmRequest, true );
return;
}
else
{
LOGGER.trace( pwmRequest, () -> "configuration password is not correct" );
pwmApplication.getIntruderManager().convenience().markAddressAndSession( pwmRequest.getPwmSession() );
pwmApplication.getIntruderManager().mark( RecordType.USERNAME, PwmConstants.CONFIGMANAGER_INTRUDER_USERNAME, pwmRequest.getSessionLabel() );
final ErrorInformation errorInformation = new ErrorInformation( PwmError.ERROR_PASSWORD_ONLY_BAD );
updateLoginHistory( pwmRequest, pwmRequest.getUserInfoIfLoggedIn(), false );
setLastError( pwmRequest, errorInformation );
forwardToJsp( pwmRequest );
return;
}
}
}
@Override
protected ConfigManagerLoginAction readProcessAction( final PwmRequest request )
throws PwmUnrecoverableException
{
try
{
return ConfigManagerLoginAction.valueOf( request.readParameterAsString( PwmConstants.PARAM_ACTION_REQUEST ) );
}
catch ( IllegalArgumentException e )
{
return null;
}
}
private static void forwardToJsp( final PwmRequest pwmRequest )
throws ServletException, PwmUnrecoverableException, IOException
{
final int persistentSeconds = figureMaxLoginSeconds( pwmRequest );
final String time = TimeDuration.of( persistentSeconds, TimeDuration.Unit.SECONDS ).asLongString( pwmRequest.getLocale() );
final ConfigLoginHistory configLoginHistory = readConfigLoginHistory( pwmRequest );
pwmRequest.setAttribute( PwmRequestAttribute.ConfigLoginHistory, configLoginHistory );
pwmRequest.setAttribute( PwmRequestAttribute.ConfigPasswordRememberTime, time );
pwmRequest.forwardToJsp( JspUrl.CONFIG_MANAGER_LOGIN );
}
private static ConfigLoginHistory readConfigLoginHistory( final PwmRequest pwmRequest )
{
final ConfigLoginHistory configLoginHistory = pwmRequest.getPwmApplication().readAppAttribute( PwmApplication.AppAttribute.CONFIG_LOGIN_HISTORY, ConfigLoginHistory.class );
return configLoginHistory == null
? new ConfigLoginHistory()
: configLoginHistory;
}
private static void updateLoginHistory( final PwmRequest pwmRequest, final UserIdentity userIdentity, final boolean successful )
{
final ConfigLoginHistory configLoginHistory = readConfigLoginHistory( pwmRequest );
final ConfigLoginEvent event = new ConfigLoginEvent(
userIdentity == null ? "n/a" : userIdentity.toDisplayString(),
Instant.now(),
pwmRequest.getPwmSession().getSessionStateBean().getSrcAddress()
);
final int maxEvents = Integer.parseInt( pwmRequest.getPwmApplication().getConfig().readAppProperty( AppProperty.CONFIG_HISTORY_MAX_ITEMS ) );
configLoginHistory.addEvent( event, maxEvents, successful );
pwmRequest.getPwmApplication().writeAppAttribute( PwmApplication.AppAttribute.CONFIG_LOGIN_HISTORY, configLoginHistory );
}
@Value
public static class ConfigLoginHistory implements Serializable
{
private List<ConfigLoginEvent> successEvents = new ArrayList<>();
private List<ConfigLoginEvent> failedEvents = new ArrayList<>();
void addEvent( final ConfigLoginEvent event, final int maxEvents, final boolean successful )
{
final List<ConfigLoginEvent> events = successful ? successEvents : failedEvents;
events.add( event );
if ( maxEvents > 0 )
{
while ( events.size() > maxEvents )
{
events.remove( 0 );
}
}
}
public List<ConfigLoginEvent> successEvents( )
{
return Collections.unmodifiableList( successEvents );
}
public List<ConfigLoginEvent> failedEvents( )
{
return Collections.unmodifiableList( failedEvents );
}
}
@Value
public static class ConfigLoginEvent implements Serializable
{
private final String userIdentity;
private final Instant date;
private final String networkAddress;
}
private static ProcessStatus processLoginSuccess( final PwmRequest pwmRequest, final boolean persistentLoginEnabled )
throws PwmUnrecoverableException, IOException
{
final ConfigManagerBean configManagerBean = pwmRequest.getPwmApplication().getSessionStateService().getBean( pwmRequest, ConfigManagerBean.class );
final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
final PwmSession pwmSession = pwmRequest.getPwmSession();
configManagerBean.setPasswordVerified( true );
pwmApplication.getIntruderManager().convenience().clearAddressAndSession( pwmSession );
pwmApplication.getIntruderManager().clear( RecordType.USERNAME, PwmConstants.CONFIGMANAGER_INTRUDER_USERNAME );
pwmRequest.getPwmSession().getSessionStateBean().setSessionIdRecycleNeeded( true );
if ( persistentLoginEnabled && "on".equals( pwmRequest.readParameterAsString( "remember" ) ) )
{
writePersistentLoginCookie( pwmRequest );
}
if ( configManagerBean.getPrePasswordEntryUrl() != null )
{
final String originalUrl = configManagerBean.getPrePasswordEntryUrl();
configManagerBean.setPrePasswordEntryUrl( null );
pwmRequest.getPwmResponse().sendRedirect( originalUrl );
return ProcessStatus.Halt;
}
pwmRequest.sendRedirect( pwmRequest.getURLwithQueryString() );
return ProcessStatus.Continue;
}
private static void forwardToNextUrl( final PwmRequest pwmRequest )
throws IOException, PwmUnrecoverableException
{
final ConfigManagerBean configManagerBean = pwmRequest.getPwmApplication().getSessionStateService().getBean( pwmRequest, ConfigManagerBean.class );
if ( configManagerBean.getPrePasswordEntryUrl() != null )
{
final String originalUrl = configManagerBean.getPrePasswordEntryUrl();
configManagerBean.setPrePasswordEntryUrl( null );
pwmRequest.getPwmResponse().sendRedirect( originalUrl );
return;
}
pwmRequest.sendRedirect( PwmServletDefinition.ConfigManager );
}
public static void writePersistentLoginCookie( final PwmRequest pwmRequest )
throws PwmUnrecoverableException
{
final int persistentSeconds = figureMaxLoginSeconds( pwmRequest );
if ( persistentSeconds > 0 )
{
final TimeDuration persistenceDuration = TimeDuration.of( persistentSeconds, TimeDuration.Unit.SECONDS );
final Instant expirationDate = persistenceDuration.incrementFromInstant( Instant.now() );
final StoredConfigurationImpl storedConfig = pwmRequest.getConfig().getStoredConfiguration();
final String persistentLoginValue = makePersistentLoginPassword( pwmRequest, storedConfig );
final PersistentLoginInfo persistentLoginInfo = new PersistentLoginInfo( expirationDate, persistentLoginValue );
final String cookieValue = pwmRequest.getPwmApplication().getSecureService().encryptObjectToString( persistentLoginInfo );
pwmRequest.getPwmResponse().writeCookie(
COOKIE_NAME,
cookieValue,
persistentSeconds,
COOKIE_PATH
);
LOGGER.debug( pwmRequest, () -> "set persistent config login cookie (expires "
+ JavaHelper.toIsoDate( expirationDate )
+ ")"
);
}
}
private static void checkPersistentLoginCookie(
final PwmRequest pwmRequest
)
throws PwmUnrecoverableException
{
if ( !persistentLoginEnabled( pwmRequest ) )
{
return;
}
final ConfigurationReader runningConfigReader = ContextManager.getContextManager( pwmRequest.getHttpServletRequest().getSession() ).getConfigReader();
final StoredConfigurationImpl storedConfig = runningConfigReader.getStoredConfiguration();
try
{
final String cookieValue = pwmRequest.readCookie( COOKIE_NAME );
if ( !StringUtil.isEmpty( cookieValue ) )
{
final PersistentLoginInfo persistentLoginInfo = pwmRequest.getPwmApplication().getSecureService().decryptObject( cookieValue, PersistentLoginInfo.class );
if ( persistentLoginInfo != null )
{
if ( persistentLoginInfo.getExpireDate().isAfter( Instant.now() ) )
{
final String persistentLoginPassword = makePersistentLoginPassword( pwmRequest, storedConfig );
if ( StringUtil.nullSafeEquals( persistentLoginPassword, persistentLoginInfo.getPassword() ) )
{
LOGGER.debug( pwmRequest, () -> "accepting persistent config login from cookie (expires "
+ JavaHelper.toIsoDate( persistentLoginInfo.getExpireDate() )
+ ")"
);
final ConfigManagerBean configManagerBean = pwmRequest.getPwmApplication().getSessionStateService().getBean( pwmRequest, ConfigManagerBean.class );
configManagerBean.setPasswordVerified( true );
}
}
pwmRequest.getPwmResponse().removeCookie( COOKIE_NAME, COOKIE_PATH );
LOGGER.debug( pwmRequest, () -> "removing non-working persistent config login cookie" );
}
}
}
catch ( Exception e )
{
LOGGER.error( pwmRequest, "error examining persistent config login cookie: " + e.getMessage() );
}
}
@Value
private static class PersistentLoginInfo implements Serializable
{
@SerializedName( "e" )
private Instant expireDate;
@SerializedName( "p" )
private String password;
}
public static int figureMaxLoginSeconds( final PwmRequest pwmRequest )
{
return JavaHelper.silentParseInt(
pwmRequest.getConfig().readAppProperty( AppProperty.CONFIG_MAX_PERSISTENT_LOGIN_SECONDS ),
(int) TimeDuration.HOUR.as( TimeDuration.Unit.SECONDS )
);
}
private static String makePersistentLoginPassword(
final PwmRequest pwmRequest,
final StoredConfiguration storedConfig
)
throws PwmUnrecoverableException
{
final int hashChars = 32;
String hashValue = storedConfig.readConfigProperty( ConfigurationProperty.PASSWORD_HASH );
if ( PwmApplicationMode.RUNNING == pwmRequest.getPwmApplication().getApplicationMode() )
{
final PwmSession pwmSession = pwmRequest.getPwmSession();
hashValue += pwmSession.getUserInfo().getUserIdentity().toDelimitedKey();
}
return StringUtil.truncate( SecureEngine.hash( hashValue, PwmHashAlgorithm.SHA512 ), hashChars );
}
private static boolean persistentLoginEnabled(
final PwmRequest pwmRequest
)
{
if ( pwmRequest.getConfig().isDefaultValue( PwmSetting.PWM_SECURITY_KEY ) )
{
LOGGER.debug( pwmRequest, () -> "security not available, persistent login not possible." );
return false;
}
return true;
}
}

View file

@ -39,11 +39,13 @@ import password.pwm.http.HttpContentType;
import password.pwm.http.HttpHeader;
import password.pwm.http.HttpMethod;
import password.pwm.http.JspUrl;
import password.pwm.http.ProcessStatus;
import password.pwm.http.PwmRequest;
import password.pwm.http.PwmRequestAttribute;
import password.pwm.http.PwmResponse;
import password.pwm.http.PwmSession;
import password.pwm.http.bean.ConfigManagerBean;
import password.pwm.http.filter.ConfigAccessFilter;
import password.pwm.http.servlet.AbstractPwmServlet;
import password.pwm.http.servlet.PwmServletDefinition;
import password.pwm.http.servlet.configguide.ConfigGuideUtils;
@ -121,9 +123,23 @@ public class ConfigManagerServlet extends AbstractPwmServlet
}
}
public static void verifyConfigAccess( final PwmRequest pwmRequest )
throws ServletException, PwmUnrecoverableException, IOException
{
final ConfigManagerBean configManagerBean = pwmRequest.getPwmApplication().getSessionStateService().getBean( pwmRequest, ConfigManagerBean.class );
final ProcessStatus processStatus = ConfigAccessFilter.checkAuthentication( pwmRequest, configManagerBean );
if ( processStatus != ProcessStatus.Continue )
{
final String msg = "config access authentication not yet completed";
throw PwmUnrecoverableException.newException( PwmError.ERROR_SERVICE_NOT_AVAILABLE, msg );
}
}
protected void processAction( final PwmRequest pwmRequest )
throws ServletException, IOException, ChaiUnavailableException, PwmUnrecoverableException
{
verifyConfigAccess( pwmRequest );
final ConfigManagerAction processAction = readProcessAction( pwmRequest );
if ( processAction != null )
{

View file

@ -20,7 +20,6 @@
package password.pwm.http.servlet.configmanager;
import com.novell.ldapchai.exception.ChaiUnavailableException;
import lombok.Builder;
import lombok.Value;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
@ -102,8 +101,9 @@ public class ConfigManagerWordlistServlet extends AbstractPwmServlet
}
protected void processAction( final PwmRequest pwmRequest )
throws ServletException, IOException, ChaiUnavailableException, PwmUnrecoverableException
throws ServletException, IOException, PwmUnrecoverableException
{
ConfigManagerServlet.verifyConfigAccess( pwmRequest );
final ConfigManagerAction processAction = readProcessAction( pwmRequest );
if ( processAction != null )

View file

@ -51,8 +51,7 @@ class ResourceFileRequest
private static final PwmLogger LOGGER = PwmLogger.forClass( ResourceFileRequest.class );
private static final Map<String, String> WEB_JAR_VERSION_MAP = Collections.unmodifiableMap( new HashMap<>( new WebJarAssetLocator().getWebJars() ) );
private static final Collection<String> WEB_JAR_ASSET_LIST = Collections.unmodifiableCollection( new ArrayList<>( new WebJarAssetLocator().getFullPathIndex().values() ) );
private static final Collection<String> WEB_JAR_ASSET_LIST = Collections.unmodifiableCollection( new ArrayList<>( new WebJarAssetLocator().listAssets() ) );
private final HttpServletRequest httpServletRequest;
private final Configuration configuration;
private final ResourceServletConfiguration resourceServletConfiguration;

View file

@ -78,19 +78,23 @@ class ReportSettings implements Serializable
{
final ReportSettings.ReportSettingsBuilder builder = ReportSettings.builder();
builder.maxCacheAge( TimeDuration.of( Long.parseLong( config.readAppProperty( AppProperty.REPORTING_MAX_REPORT_AGE_SECONDS ) ), TimeDuration.Unit.SECONDS ) );
builder.searchFilter( config.readSettingAsUserPermission( PwmSetting.REPORTING_USER_MATCH ) );
builder.maxSearchSize ( ( int ) config.readSettingAsLong( PwmSetting.REPORTING_MAX_QUERY_SIZE ) );
builder.dailyJobEnabled( config.readSettingAsBoolean( PwmSetting.REPORTING_ENABLE_DAILY_JOB ) );
if ( builder.searchFilter == null || builder.searchFilter.isEmpty() )
{
builder.searchFilter = null;
final List<UserPermission> searchFilter = config.readSettingAsUserPermission( PwmSetting.REPORTING_USER_MATCH );
if ( searchFilter != null && !searchFilter.isEmpty() )
{
builder.searchFilter( searchFilter );
}
}
builder.jobOffsetSeconds = ( int ) config.readSettingAsLong( PwmSetting.REPORTING_JOB_TIME_OFFSET );
if ( builder.jobOffsetSeconds > 60 * 60 * 24 )
{
builder.jobOffsetSeconds = 0;
final int jobOffsetSeconds = ( int ) config.readSettingAsLong( PwmSetting.REPORTING_JOB_TIME_OFFSET );
if ( jobOffsetSeconds <= 60 * 60 * 24 )
{
builder.jobOffsetSeconds( jobOffsetSeconds );
}
}
builder.trackDays( parseDayIntervalStr( config ) );

View file

@ -338,16 +338,19 @@ public class CaptchaUtility
final String configValue = pwmRequest.getConfig().readSettingAsString( PwmSetting.CAPTCHA_SKIP_PARAM );
if ( !StringUtil.isEmpty( configValue ) )
{
final String skipCaptcha = pwmRequest.readParameterAsString( PwmConstants.PARAM_SKIP_CAPTCHA );
if ( StringUtil.nullSafeEquals( configValue, skipCaptcha ) )
final String requestValue = pwmRequest.readParameterAsString( PwmConstants.PARAM_SKIP_CAPTCHA );
if ( !StringUtil.isEmpty( requestValue ) )
{
LOGGER.trace( pwmRequest, () -> "valid skipCaptcha value in request, skipping captcha check for this session" );
pwmRequest.getPwmSession().getSessionStateBean().setCaptchaBypassedViaParameter( true );
return true;
}
else
{
LOGGER.error( pwmRequest, "skipCaptcha value is in request, however value '" + skipCaptcha + "' does not match configured value" );
if ( StringUtil.nullSafeEquals( configValue, requestValue ) )
{
LOGGER.trace( pwmRequest, () -> "valid skipCaptcha value in request, skipping captcha check for this session" );
pwmRequest.getPwmSession().getSessionStateBean().setCaptchaBypassedViaParameter( true );
return true;
}
else
{
LOGGER.error( pwmRequest, "skipCaptcha value is in request, however value '" + requestValue + "' does not match configured value" );
}
}
}

View file

@ -64,7 +64,7 @@ public class MBeanUtility
}
catch ( Exception e )
{
LOGGER.error( "error registering mbean: " + e.getMessage() );
LOGGER.debug( () -> "error registering mbean: " + e.getMessage() );
}
}
@ -77,7 +77,7 @@ public class MBeanUtility
}
catch ( Exception e )
{
LOGGER.error( "error unregistering mbean: " + e.getMessage() );
LOGGER.debug( () -> "error unregistering mbean: " + e.getMessage() );
}
}

View file

@ -35,7 +35,6 @@ import password.pwm.config.option.DataStorageMethod;
import password.pwm.error.PwmUnrecoverableException;
import password.pwm.util.logging.PwmLogger;
import java.time.Instant;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -119,7 +118,7 @@ public interface CrOperator
);
responseInfoBean.setTimestamp( responseSet.getTimestamp() == null
? null
: Instant.ofEpochMilli( responseSet.getTimestamp().getTime() )
: responseSet.getTimestamp()
);
return responseInfoBean;
}

View file

@ -101,7 +101,6 @@ import java.security.Security;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@ -620,7 +619,7 @@ public class NMASCrOperator implements CrOperator
}
@Override
public Date getTimestamp( ) throws ChaiUnavailableException, IllegalStateException, ChaiOperationException
public Instant getTimestamp( ) throws ChaiUnavailableException, IllegalStateException, ChaiOperationException
{
return null;
}

View file

@ -3,7 +3,7 @@
<parent>
<groupId>org.pwm-project</groupId>
<artifactId>pwm-parent</artifactId>
<version>1.9.0</version>
<version>1.9.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -181,7 +181,7 @@
<!-- builds xml file of dependencies and licenses for use in about page -->
<groupId>com.github.jinnovations</groupId>
<artifactId>attribution-maven-plugin</artifactId>
<version>0.9.5</version>
<version>0.9.8</version>
<executions>
<execution>
<goals>
@ -285,22 +285,22 @@
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>dojo</artifactId>
<version>1.15.0</version>
<version>1.16.4</version>
</dependency>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>dijit</artifactId>
<version>1.15.0</version>
<version>1.16.4</version>
</dependency>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>dojox</artifactId>
<version>1.15.0</version>
<version>1.16.4</version>
</dependency>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>dgrid</artifactId>
<version>1.2.1</version>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>org.webjars.bower</groupId>

View file

@ -73,6 +73,8 @@
<exclude>.node/**</exclude>
<exclude>dist/**</exclude>
<exclude>node_modules/**</exclude>
<exclude>angular/dist/**</exclude>
<exclude>angular/node_modules/**</exclude>
</excludes>
</fileSet>
<fileSet>

View file

@ -24,6 +24,8 @@
<%@ page import="password.pwm.util.i18n.LocaleHelper" %>
<%@ page import="password.pwm.util.java.JavaHelper" %>
<%@ page import="password.pwm.http.PwmRequestAttribute" %>
<%@ page import="password.pwm.http.servlet.configmanager.ConfigManagerServlet" %>
<%@ page import="password.pwm.http.servlet.configmanager.ConfigManagerLoginServlet" %>
<!DOCTYPE html>
@ -66,11 +68,12 @@
<pwm:if test="<%=PwmIfTest.showIcons%>"><span class="btn-icon pwm-icon pwm-icon-sign-in"></span></pwm:if>
<pwm:display key="Button_Login"/>
</button>
<input type="hidden" name="processAction" value="<%=ConfigManagerLoginServlet.ConfigManagerLoginAction.login%>"/>
<%@ include file="/WEB-INF/jsp/fragment/cancel-button.jsp" %>
<input type="hidden" id="pwmFormID" name="pwmFormID" value="<pwm:FormID/>" autofocus/>
</div>
</form>
<% final ConfigAccessFilter.ConfigLoginHistory configLoginHistory = (ConfigAccessFilter.ConfigLoginHistory)JspUtility.getAttribute(pageContext, PwmRequestAttribute.ConfigLoginHistory); %>
<% final ConfigManagerLoginServlet.ConfigLoginHistory configLoginHistory = (ConfigManagerLoginServlet.ConfigLoginHistory)JspUtility.getAttribute(pageContext, PwmRequestAttribute.ConfigLoginHistory); %>
<% if (configLoginHistory != null && !configLoginHistory.successEvents().isEmpty()) { %>
<h2 style="margin-top: 15px;">Previous Authentications</h2>
<table>
@ -79,7 +82,7 @@
<td class="title">Timestamp</td>
<td class="title">Network Address</td>
</tr>
<% for (final ConfigAccessFilter.ConfigLoginEvent event : configLoginHistory.successEvents()) { %>
<% for (final ConfigManagerLoginServlet.ConfigLoginEvent event : configLoginHistory.successEvents()) { %>
<tr>
<td><%=event.getUserIdentity()%></td>
<td><span class="timestamp"><%=JavaHelper.toIsoDate(event.getDate())%></span></td>
@ -97,7 +100,7 @@
<td class="title">Timestamp</td>
<td class="title">Network Address</td>
</tr>
<% for (final ConfigAccessFilter.ConfigLoginEvent event : configLoginHistory.failedEvents()) { %>
<% for (final ConfigManagerLoginServlet.ConfigLoginEvent event : configLoginHistory.failedEvents()) { %>
<tr>
<td><%=event.getUserIdentity()%></td>
<td><span class="timestamp"><%=JavaHelper.toIsoDate(event.getDate())%></span></td>