show password prompt if user with expired password logs in

This commit is contained in:
Roland Gruber 2020-06-18 13:08:23 +02:00
parent 55ccddbf1e
commit 30909b385a
9 changed files with 270 additions and 34 deletions

View File

@ -1,5 +1,6 @@
September 2020
- PHP 7.4 compatibility
- Show password prompt when a user with expired password logs into LAM admin interface (requires PHP 7.2)
- Windows users: group display format can be configured (cn/dn)
01.05.2020 7.2

View File

@ -503,6 +503,9 @@
</listitem>
</itemizedlist>
<para>Hide password prompt for expired password: Hides the password
prompt when a user with expired password logs into LAM.</para>
<literallayout>
</literallayout>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 78 KiB

View File

@ -243,6 +243,8 @@ $helpArray = array (
"Text" => _('This email address will be set as sender address of the mails.')),
'290' => array ("Headline" => _('TO address'),
"Text" => _('This email address will be set as TO address for the mails.')),
"291" => array ("Headline" => _('Hide password prompt for expired password'),
"Text" => _('Hides the password prompt when a user with expired password logs into LAM.')),
// 300 - 399
// profile editor, file upload
"301" => array ("Headline" => _("RDN identifier"),

View File

@ -100,9 +100,9 @@ function setlanguage() {
/**
* Checks whether a specific flag in the rights string is set.
*
* @param $right read,write or execute
* @param $target owner,group or other
* @param $chmod the chmod rights
* @param string $right read, write or execute
* @param string $target owner, group or other
* @param string $chmod the chmod rights
*
* @return true, if the chmod $right for $target were set
*/
@ -467,6 +467,9 @@ class LAMConfig {
/** overlay for referential integrity is activated */
private $referentialIntegrityOverlay = 'false';
/** hide password prompt for expired passwords */
private $hidePasswordPromptForExpiredPasswords = 'false';
/** Array of string: users with admin rights */
private $Admins;
@ -626,7 +629,8 @@ class LAMConfig {
'scriptUserName', 'scriptSSHKey', 'scriptSSHKeyPassword', 'twoFactorAuthentication', 'twoFactorAuthenticationURL',
'twoFactorAuthenticationInsecure', 'twoFactorAuthenticationLabel', 'twoFactorAuthenticationOptional',
'twoFactorAuthenticationCaption', 'twoFactorAuthenticationClientId', 'twoFactorAuthenticationSecretKey',
'twoFactorAuthenticationDomain', 'twoFactorAuthenticationAttribute', 'referentialIntegrityOverlay'
'twoFactorAuthenticationDomain', 'twoFactorAuthenticationAttribute', 'referentialIntegrityOverlay',
'hidePasswordPromptForExpiredPasswords'
);
@ -933,6 +937,9 @@ class LAMConfig {
if (!in_array("referentialIntegrityOverlay", $saved)) {
array_push($file_array, "\n" . "referentialIntegrityOverlay: " . $this->referentialIntegrityOverlay . "\n");
}
if (!in_array("hidePasswordPromptForExpiredPasswords", $saved)) {
array_push($file_array, "\n" . "hidePasswordPromptForExpiredPasswords: " . $this->hidePasswordPromptForExpiredPasswords . "\n");
}
if (!in_array("Passwd", $saved)) {
array_push($file_array, "\n\n# password to change these preferences via webfrontend\n" . "Passwd: " . $this->Passwd . "\n");
}
@ -1176,10 +1183,12 @@ class LAMConfig {
* @return boolean true if $value has correct format
*/
public function set_ServerURL($value) {
if (is_string($value)) $this->ServerURL = $value;
else return false;
if (is_string($value)) {
$this->ServerURL = $value;
return true;
}
return false;
}
/**
* Returns the server display name. Defaults to server URL if empty display name.
@ -1209,10 +1218,12 @@ class LAMConfig {
* @return boolean true if $value has correct format
*/
public function setServerDisplayName($value) {
if (is_string($value)) $this->serverDisplayName = $value;
else return false;
if (is_string($value)) {
$this->serverDisplayName = $value;
return true;
}
return false;
}
/**
* Returns if TLS is activated.
@ -1300,6 +1311,33 @@ class LAMConfig {
return $this->referentialIntegrityOverlay === 'true';
}
/**
* Hide password prompt for expired passwords.
*
* @return String true or false
*/
public function getHidePasswordPromptForExpiredPasswords() {
return $this->hidePasswordPromptForExpiredPasswords;
}
/**
* Sets if password prompt for expired passwords is hidden.
*
* @param String $hidePasswordPromptForExpiredPasswords true or false
*/
public function setHidePasswordPromptForExpiredPasswords($hidePasswordPromptForExpiredPasswords) {
$this->hidePasswordPromptForExpiredPasswords = $hidePasswordPromptForExpiredPasswords;
}
/**
* Hide password prompt for expired passwords.
*
* @return bool is hidden
*/
public function isHidePasswordPromptForExpiredPasswords() {
return $this->hidePasswordPromptForExpiredPasswords === 'true';
}
/**
* Returns an array of string with all admin names
*
@ -1328,10 +1366,10 @@ class LAMConfig {
if (is_string($value) &&
preg_match("/^[^;]+(;[^;]+)*$/", $value)) {
$this->Admins = $value;
}
else return false;
return true;
}
return false;
}
/**
* Checks if the given password matches.
@ -1406,7 +1444,9 @@ class LAMConfig {
* @return boolean true if $value has correct format
*/
public function set_Suffix($scope, $value) {
if (!$value) $value = "";
if (!$value) {
$value = "";
}
elseif (!is_string($value)) {
return false;
}
@ -1771,10 +1811,10 @@ class LAMConfig {
public function set_searchLimit($value) {
if (is_numeric($value) && ($value > -1)) {
$this->searchLimit = $value;
}
else return false;
return true;
}
return false;
}
/**
* Returns an array of all selected account modules

View File

@ -0,0 +1,148 @@
<?php
namespace LAM\INIT;
use htmlButton;
use htmlOutputText;
use htmlResponsiveInputField;
use htmlResponsiveRow;
use htmlStatusMessage;
/*
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2020 Roland Gruber
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
*/
/**
* Password change dialog for expired passwords.
*
* @author Roland Gruber
* @package main
*/
/** security functions */
include_once(__DIR__ . "/../lib/security.inc");
/** access to configuration settings */
include_once(__DIR__ . "/../lib/config.inc");
/** LDAP access */
include_once(__DIR__ . "/../lib/ldap.inc");
/** status messages */
include_once(__DIR__ . "/../lib/status.inc");
// start session
startSecureSession();
enforceUserIsLoggedIn();
if (!checkIfWriteAccessIsAllowed()) {
die();
}
setlanguage();
if (!empty($_POST)) {
validateSecurityToken();
}
$message = null;
// check if user already pressed button
if (isset($_POST['changePassword'])) {
// check new password
$password1 = $_POST['password1'];
$password2 = $_POST['password2'];
if ($password1 == '') {
$message = new htmlStatusMessage('ERROR', _('No password was entered!'));
printContent($message);
exit();
}
// check if passwords match
if ($password1 != $password2) {
$message = new htmlStatusMessage('ERROR', _('Passwords are different!'));
printContent($message);
exit();
}
// check passsword strength
$userDn = $_SESSION['ldap']->getUserName();
$additionalAttrs = array();
$rdnAttr = extractRDNAttribute($userDn);
$userName = null;
if (($rdnAttr === 'uid') || ($rdnAttr === 'uid')) {
$userName = extractRDNValue($userDn);
}
$pwdPolicyResult = checkPasswordStrength($password1, $userName, $additionalAttrs);
if ($pwdPolicyResult !== true) {
$message = new htmlStatusMessage('ERROR', $pwdPolicyResult);
printContent($message);
exit();
}
// set new password
$modifyResult = @ldap_exop_passwd($_SESSION['ldap']->server(), $userDn, $_SESSION['ldap']->getPassword(), $password1);
if ($modifyResult === true) {
$_SESSION['ldap']->encrypt_login($userDn, $password1);
$message = new htmlStatusMessage('INFO', _('Password changed.'));
printContent($message, false);
exit();
}
else {
$message = new htmlStatusMessage('ERROR', _('Unable to set password'), getExtendedLDAPErrorMessage($_SESSION['ldap']->server()));
printContent($message);
exit();
}
}
printContent($message);
/**
* Displays the content area
*
* @param htmlStatusMessage $message status message
* @param bool $showPasswordInputs show password input fields
*/
function printContent($message = null, $showPasswordInputs = true) {
include __DIR__ . '/../lib/adminHeader.inc';
echo '<div class="user-bright smallPaddingContent">';
echo "<form action=\"changePassword.php\" method=\"post\">\n";
$container = new htmlResponsiveRow();
if ($message !== null) {
$container->addVerticalSpacer('1rem');
$container->add($message, 12);
}
$container->addVerticalSpacer('2rem');
if ($showPasswordInputs) {
$container->add(new htmlOutputText(_("It seems your password expired. You can set a new one here.")), 12, 12, 12, 'text-center');
$container->addVerticalSpacer('2rem');
$pwdInput1 = new htmlResponsiveInputField(_('New password'), 'password1', '');
$pwdInput1->setIsPassword(true, true, true);
$container->add($pwdInput1, 12);
$pwdInput2 = new htmlResponsiveInputField(_('Repeat password'), 'password2', '');
$pwdInput2->setIsPassword(true);
$pwdInput2->setSameValueFieldID('password1');
$container->add($pwdInput2, 12);
$container->addVerticalSpacer('1rem');
$container->add(new htmlButton('changePassword', _("Submit")), 12, 12, 12, 'text-center');
addSecurityTokenToMetaHTML($container);
}
$tabindex = 1;
parseHtml(null, $container, array(), false, $tabindex, 'user');
echo "</form><br>\n";
echo "</div>\n";
include __DIR__ . '/../lib/adminFooter.inc';
}

View File

@ -234,6 +234,11 @@ $advancedOptionsContent->add(new htmlResponsiveInputCheckbox('pagedResults', $pa
// referential integrity overlay
$referentialIntegrity = ($conf->isReferentialIntegrityOverlayActive());
$advancedOptionsContent->add(new htmlResponsiveInputCheckbox('referentialIntegrityOverlay', $referentialIntegrity , _('Referential integrity overlay'), '269'), 12);
// hide password prompt for expired passwords
if (version_compare(phpversion(), '7.2.0') >= 0) {
$hidePasswordPromptForExpiredPasswords = ($conf->isHidePasswordPromptForExpiredPasswords());
$advancedOptionsContent->add(new htmlResponsiveInputCheckbox('hidePasswordPromptForExpiredPasswords', $hidePasswordPromptForExpiredPasswords, _('Hide password prompt for expired password'), '291'), 12);
}
// build advanced options box
$advancedOptions = new htmlAccordion('advancedOptions_server', array(_('Advanced options') => $advancedOptionsContent), false);
@ -585,6 +590,14 @@ function checkInput() {
else {
$conf->setReferentialIntegrityOverlay('false');
}
if (version_compare(phpversion(), '7.2.0') >= 0) {
if (isset($_POST['hidePasswordPromptForExpiredPasswords']) && ($_POST['hidePasswordPromptForExpiredPasswords'] == 'on')) {
$conf->setHidePasswordPromptForExpiredPasswords('true');
}
else {
$conf->setHidePasswordPromptForExpiredPasswords('false');
}
}
/* if (!$conf->set_cacheTimeout($_POST['cachetimeout'])) {
$errors[] = array("ERROR", _("Cache timeout is invalid!"));
}*/

View File

@ -1,10 +1,12 @@
<?php
namespace LAM\INIT;
use locking389ds;
/*
$Id$
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2003 - 2017 Roland Gruber
Copyright (C) 2003 - 2020 Roland Gruber
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
@ -43,8 +45,24 @@ setlanguage();
\LAM\PROFILES\installProfileTemplates();
\LAM\PDF\installPDFTemplates();
// check if all suffixes in conf-file exist
$conf = $_SESSION['config'];
// check if user password is not expired
if ((version_compare(phpversion(), '7.2.0') >= 0) && !$conf->isHidePasswordPromptForExpiredPasswords()) {
$userDn = $_SESSION['ldap']->getUserName();
$userData = ldapGetDN($userDn, array('*', '+', 'pwdReset', 'passwordExpirationTime'));
$ldapErrorCode = ldap_errno($_SESSION['ldap']->server());
if ($ldapErrorCode != 32) {
$pwdResetMarker = (!empty($userData['pwdreset'][0]) && ($userData['pwdreset'][0] == 'TRUE'));
$pwdExpiration = (!empty($userData)) && locking389ds::isPasswordExpired($userData);
if (($userData === null) || $pwdResetMarker || $pwdExpiration) {
metaRefresh("changePassword.php");
exit();
}
}
}
// check if all suffixes in conf-file exist
$new_suffs = array();
// get list of active types
$typeManager = new \LAM\TYPES\TypeManager();
@ -64,20 +82,17 @@ foreach ($types as $type) {
// display page to add suffixes, if needed
if ((sizeof($new_suffs) > 0) && checkIfWriteAccessIsAllowed()) {
metaRefresh("initsuff.php?suffs='" . implode(";", $new_suffs));
exit();
}
else {
if (sizeof($types) > 0) {
foreach ($types as $type) {
if ($type->isHidden()) {
continue;
}
metaRefresh("lists/list.php?type=" . $type->getId());
break;
}
}
else {
metaRefresh("tree/treeViewContainer.php");
exit();
}
}
?>
metaRefresh("tree/treeViewContainer.php");

View File

@ -167,6 +167,20 @@ class LAMConfigTest extends TestCase {
$this->assertTrue($this->lAMConfig->isReferentialIntegrityOverlayActive());
}
/**
* Tests LAMConfig->getHidePasswordPromptForExpiredPasswords() and LAMConfig->setHidePasswordPromptForExpiredPasswords()
*/
public function testHidePasswordPromptForExpiredPasswords() {
$this->assertFalse($this->lAMConfig->isHidePasswordPromptForExpiredPasswords());
$val = 'true';
$this->lAMConfig->setHidePasswordPromptForExpiredPasswords($val);
$this->assertEquals($val, $this->lAMConfig->getHidePasswordPromptForExpiredPasswords());
$this->assertTrue($this->lAMConfig->isHidePasswordPromptForExpiredPasswords());
$this->doSave();
$this->assertEquals($val, $this->lAMConfig->getHidePasswordPromptForExpiredPasswords());
$this->assertTrue($this->lAMConfig->isHidePasswordPromptForExpiredPasswords());
}
/**
* Tests LAMConfig->get_Admins()
*/