diff --git a/lam/HISTORY b/lam/HISTORY index 20255fc8..0670b1ab 100644 --- a/lam/HISTORY +++ b/lam/HISTORY @@ -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 diff --git a/lam/docs/manual-sources/chapter-configuration.xml b/lam/docs/manual-sources/chapter-configuration.xml index cc1ce670..d7fe125f 100644 --- a/lam/docs/manual-sources/chapter-configuration.xml +++ b/lam/docs/manual-sources/chapter-configuration.xml @@ -503,6 +503,9 @@ + Hide password prompt for expired password: Hides the password + prompt when a user with expired password logs into LAM. + diff --git a/lam/docs/manual-sources/images/configProfiles4.png b/lam/docs/manual-sources/images/configProfiles4.png index d475cd05..ef81788f 100644 Binary files a/lam/docs/manual-sources/images/configProfiles4.png and b/lam/docs/manual-sources/images/configProfiles4.png differ diff --git a/lam/help/help.inc b/lam/help/help.inc index 9ec58a10..8c6162d5 100644 --- a/lam/help/help.inc +++ b/lam/help/help.inc @@ -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"), diff --git a/lam/lib/config.inc b/lam/lib/config.inc index 4743d72f..b674d828 100644 --- a/lam/lib/config.inc +++ b/lam/lib/config.inc @@ -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,9 +1183,11 @@ 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; - return true; + if (is_string($value)) { + $this->ServerURL = $value; + return true; + } + return false; } /** @@ -1209,9 +1218,11 @@ class LAMConfig { * @return boolean true if $value has correct format */ public function setServerDisplayName($value) { - if (is_string($value)) $this->serverDisplayName = $value; - else return false; - return true; + if (is_string($value)) { + $this->serverDisplayName = $value; + return true; + } + return false; } /** @@ -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 * @@ -1326,11 +1364,11 @@ class LAMConfig { */ public function set_Adminstring($value) { if (is_string($value) && - preg_match("/^[^;]+(;[^;]+)*$/", $value)) { + preg_match("/^[^;]+(;[^;]+)*$/", $value)) { $this->Admins = $value; + return true; } - else return false; - return true; + return false; } /** @@ -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,9 +1811,9 @@ class LAMConfig { public function set_searchLimit($value) { if (is_numeric($value) && ($value > -1)) { $this->searchLimit = $value; + return true; } - else return false; - return true; + return false; } /** diff --git a/lam/templates/changePassword.php b/lam/templates/changePassword.php new file mode 100644 index 00000000..f5ada368 --- /dev/null +++ b/lam/templates/changePassword.php @@ -0,0 +1,148 @@ +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 '
'; + echo "
\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 "

\n"; + echo "
\n"; + include __DIR__ . '/../lib/adminFooter.inc'; +} diff --git a/lam/templates/config/confmain.php b/lam/templates/config/confmain.php index 65025b65..22426e24 100644 --- a/lam/templates/config/confmain.php +++ b/lam/templates/config/confmain.php @@ -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,9 +590,17 @@ function checkInput() { else { $conf->setReferentialIntegrityOverlay('false'); } -/* if (!$conf->set_cacheTimeout($_POST['cachetimeout'])) { - $errors[] = array("ERROR", _("Cache timeout is invalid!")); - }*/ + 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!")); + }*/ $conf->set_searchLimit($_POST['searchLimit']); if (isLAMProVersion()) { $conf->setAccessLevel($_POST['accessLevel']); diff --git a/lam/templates/main.php b/lam/templates/main.php index 4da6b94a..d4c4945d 100644 --- a/lam/templates/main.php +++ b/lam/templates/main.php @@ -1,10 +1,12 @@ = 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; + +if (sizeof($types) > 0) { + foreach ($types as $type) { + if ($type->isHidden()) { + continue; } - } - else { - metaRefresh("tree/treeViewContainer.php"); + metaRefresh("lists/list.php?type=" . $type->getId()); + exit(); } } -?> +metaRefresh("tree/treeViewContainer.php"); diff --git a/lam/tests/lib/LAMConfigTest.php b/lam/tests/lib/LAMConfigTest.php index b6f9212c..44bf6ae4 100644 --- a/lam/tests/lib/LAMConfigTest.php +++ b/lam/tests/lib/LAMConfigTest.php @@ -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() */