support Windows lockoutTime
This commit is contained in:
parent
7169068d93
commit
7b82372a2d
|
@ -2,6 +2,7 @@ June 2017
|
|||
- Support multiple configurations for same account type
|
||||
- PHP 7.1 compatibility
|
||||
- Samba 3: added account expiration date to PDF fields
|
||||
- Windows: Support unlocking of users with too many failed login attempts
|
||||
|
||||
|
||||
15.03.2017 5.7
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
use \LAM\TYPES\TypeManager;
|
||||
use LAM\TYPES\ConfiguredType;
|
||||
/*
|
||||
$Id$
|
||||
|
||||
|
@ -69,6 +70,9 @@ class windowsUser extends baseModule implements passwordService {
|
|||
/** business category cache */
|
||||
private $businessCategoryCache = null;
|
||||
|
||||
/** cache for lockout duration */
|
||||
private static $lockoutDurationCache = array();
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if this module can manage accounts of the current type, otherwise false.
|
||||
|
@ -111,7 +115,7 @@ class windowsUser extends baseModule implements passwordService {
|
|||
'pwdLastSet', 'otherMailbox', 'homeDirectory', 'homeDrive', 'msSFU30Name', 'msSFU30NisDomain', 'pwdLastSet',
|
||||
'lastLogonTimestamp', 'accountExpires', 'jpegPhoto', 'title', 'carLicense', 'employeeNumber', 'employeeType',
|
||||
'businessCategory', 'department', 'ou', 'o', 'manager', 'facsimileTelephoneNumber', 'company',
|
||||
'pager', 'otherPager', 'mobile', 'otherMobile', 'proxyAddresses'
|
||||
'pager', 'otherPager', 'mobile', 'otherMobile', 'proxyAddresses', 'lockoutTime'
|
||||
);
|
||||
// help Entries
|
||||
$return['help'] = array(
|
||||
|
@ -2899,6 +2903,65 @@ class windowsUser extends baseModule implements passwordService {
|
|||
return intval($myAttrs['useraccountcontrol'][0]) & windowsUser::AC_ACCOUNT_DISABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the account is currently deactivated.
|
||||
*
|
||||
* @param array $attrs LDAP attributes
|
||||
* @param ConfiguredType type
|
||||
* @return DateTime locked till or null
|
||||
*/
|
||||
public static function getPasswordLocked($attrs, $type) {
|
||||
$myAttrs = array_change_key_case($attrs, CASE_LOWER);
|
||||
if (empty($myAttrs['lockouttime'][0])) {
|
||||
return false;
|
||||
}
|
||||
$lockoutDuration = self::getDomainLockoutDuration($attrs['dn']);
|
||||
if (empty($lockoutDuration) || ($lockoutDuration > -1)) {
|
||||
return false;
|
||||
}
|
||||
$lockoutDurationSeconds = substr($lockoutDuration, 0, -7);
|
||||
$lockoutTime = self::getFileTime($myAttrs['lockouttime'][0]);
|
||||
$unlockTime = clone $lockoutTime;
|
||||
$unlockTime->add(new DateInterval('PT' . abs($lockoutDurationSeconds) . 'S'));
|
||||
$now = new DateTime();
|
||||
if ($unlockTime > $now) {
|
||||
$unlockTime->setTimezone(getTimeZone());
|
||||
return $unlockTime;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the domain lockout duration for this DN.
|
||||
*
|
||||
* @param string $dn user DN
|
||||
*/
|
||||
private static function getDomainLockoutDuration($dn) {
|
||||
$lowerDn = strtolower($dn);
|
||||
$domainRoot = substr($lowerDn, strpos($lowerDn, 'dc='));
|
||||
if (isset(windowsUser::$lockoutDurationCache[$domainRoot])) {
|
||||
return windowsUser::$lockoutDurationCache[$domainRoot];
|
||||
}
|
||||
$policyDN = 'cn=builtin,' . $domainRoot;
|
||||
$policyAttrs = ldapGetDN($policyDN, array('lockoutduration'));
|
||||
if (!empty($policyAttrs['lockoutduration'][0])) {
|
||||
windowsUser::$lockoutDurationCache[$domainRoot] = $policyAttrs['lockoutduration'][0];
|
||||
}
|
||||
else {
|
||||
windowsUser::$lockoutDurationCache[$domainRoot] = null;
|
||||
}
|
||||
return windowsUser::$lockoutDurationCache[$domainRoot];
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks the user password. This resets 'lockoutTime' to 0.
|
||||
*/
|
||||
public function unlockPassword() {
|
||||
if (!empty($this->attributes['lockoutTime'][0])) {
|
||||
$this->attributes['lockoutTime'][0] = '0';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the account is currently deactivated.
|
||||
*
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
$Id$
|
||||
|
||||
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||
Copyright (C) 2005 - 2016 Roland Gruber
|
||||
Copyright (C) 2005 - 2017 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
|
||||
|
@ -259,10 +259,22 @@ class user extends baseType {
|
|||
$ppolicyLocked = true;
|
||||
}
|
||||
$windowsLocked = false;
|
||||
if ($windowsAvailable && windowsUser::isDeactivated($container->getAccountModule('windowsUser')->getAttributes())) {
|
||||
$windowsPasswordLockedTime = null;
|
||||
$windowsPasswordLocked = false;
|
||||
if ($windowsAvailable){
|
||||
$attrs = $container->getAccountModule('windowsUser')->getAttributes();
|
||||
$attrs['dn'] = $container->dn_orig;
|
||||
if (windowsUser::isDeactivated($attrs)) {
|
||||
$windowsLocked = true;
|
||||
}
|
||||
$partiallyLocked = $unixLocked || $sambaLocked || $ppolicyLocked || $windowsLocked || $is389dsDeactivated || $is389dsLocked;
|
||||
$windowsPasswordLockedTime = windowsUser::getPasswordLocked($attrs, $this->getType());
|
||||
if ($windowsPasswordLockedTime != null) {
|
||||
$windowsPasswordLocked = true;
|
||||
}
|
||||
}
|
||||
$partiallyLocked = $unixLocked || $sambaLocked
|
||||
|| $ppolicyLocked || $windowsLocked || $windowsPasswordLocked
|
||||
|| $is389dsDeactivated || $is389dsLocked;
|
||||
$fullyLocked = ($unixAvailable || $sambaAvailable || $ppolicyAvailable || $windowsAvailable || $is389dsDeactivated || $is389dsLocked)
|
||||
&& (!$unixAvailable || $unixLocked)
|
||||
&& (!$sambaAvailable || $sambaLocked)
|
||||
|
@ -309,6 +321,9 @@ class user extends baseType {
|
|||
}
|
||||
$statusTable .= '<tr><td>' . _('Windows') . ' </td><td><img height=16 width=16 src="../../graphics/' . $windowsIcon . '"></td></tr>';
|
||||
}
|
||||
if ($windowsAvailable && $windowsPasswordLocked) {
|
||||
$statusTable .= '<tr><td>' . _('Locked till') . ' </td><td>' . $windowsPasswordLockedTime->format('Y-m-d H:i:s') . '</td></tr>';
|
||||
}
|
||||
// 389ds locked
|
||||
if ($is389dsLocked) {
|
||||
$statusTable .= '<tr><td>' . _('Locked') . ' </td><td><img height=16 width=16 src="../../graphics/lock.png"></td></tr>';
|
||||
|
@ -325,7 +340,7 @@ class user extends baseType {
|
|||
$tipContent .= '<br><img alt="hint" src="../../graphics/light.png"> ';
|
||||
$tipContent .= _('Please click to lock/unlock this account.');
|
||||
}
|
||||
$dialogDiv = $this->buildAccountStatusDialogDiv($unixAvailable, $unixLocked, $sambaAvailable, $sambaLocked, $ppolicyAvailable, $ppolicyLocked, $windowsAvailable, $windowsLocked, $is389dsAvailable, $is389dsLocked, $is389dsDeactivated);
|
||||
$dialogDiv = $this->buildAccountStatusDialogDiv($unixAvailable, $unixLocked, $sambaAvailable, $sambaLocked, $ppolicyAvailable, $ppolicyLocked, $windowsAvailable, $windowsLocked, $windowsPasswordLockedTime, $is389dsAvailable, $is389dsLocked, $is389dsDeactivated);
|
||||
$onClick = '';
|
||||
if ($isEditable) {
|
||||
$onClick = 'onclick="showConfirmationDialog(\'' . _('Change account status') . '\', \'' . _('Ok') . '\', \'' . _('Cancel') . '\', \'lam_accountStatusDialog\', \'inputForm\', \'lam_accountStatusResult\');"';
|
||||
|
@ -344,18 +359,20 @@ class user extends baseType {
|
|||
* @param boolean $ppolicyLocked PPolicy part is locked
|
||||
* @param boolean $windowsAvailable Windows part is active
|
||||
* @param boolean $windowsLocked Windows part is locked
|
||||
* @param DateTime $windowsPasswordLockedTime lock time for Windows or null
|
||||
* @param boolean $is389dsAvailable 389ds is available
|
||||
* @param boolean $is389dsLocked account is locked
|
||||
* @param boolean $is389dsDeactivated account is deactivated
|
||||
*/
|
||||
private function buildAccountStatusDialogDiv($unixAvailable, $unixLocked, $sambaAvailable, $sambaLocked, $ppolicyAvailable, $ppolicyLocked, $windowsAvailable,
|
||||
$windowsLocked, $is389dsAvailable, $is389dsLocked, $is389dsDeactivated) {
|
||||
$partiallyLocked = $unixLocked || $sambaLocked || $ppolicyLocked || $windowsLocked || $is389dsLocked || $is389dsDeactivated;
|
||||
$windowsLocked, $windowsPasswordLockedTime, $is389dsAvailable, $is389dsLocked, $is389dsDeactivated) {
|
||||
$windowsPasswordLocked = ($windowsPasswordLockedTime != null);
|
||||
$partiallyLocked = $unixLocked || $sambaLocked || $ppolicyLocked || $windowsLocked || $windowsPasswordLocked || $is389dsLocked || $is389dsDeactivated;
|
||||
$fullyLocked = ($unixAvailable || $sambaAvailable || $ppolicyAvailable || $windowsAvailable || $is389dsLocked || $is389dsDeactivated)
|
||||
&& (!$unixAvailable || $unixLocked)
|
||||
&& (!$sambaAvailable || $sambaLocked)
|
||||
&& (!$ppolicyAvailable || $ppolicyLocked)
|
||||
&& (!$windowsAvailable || $windowsLocked);
|
||||
&& (!$windowsAvailable || $windowsLocked || $windowsPasswordLocked);
|
||||
|
||||
$container = new htmlTable();
|
||||
|
||||
|
@ -454,6 +471,10 @@ class user extends baseType {
|
|||
$unlockContent->addElement(new htmlImage('../../graphics/samba.png'));
|
||||
$unlockContent->addElement(new htmlTableExtendedInputCheckbox('lam_accountStatusUnlockWindows', true, _('Windows'), null, false), true);
|
||||
}
|
||||
if ($windowsAvailable && $windowsPasswordLocked) {
|
||||
$unlockContent->addElement(new htmlImage('../../graphics/samba.png'));
|
||||
$unlockContent->addElement(new htmlTableExtendedInputCheckbox('lam_accountStatusUnlockWindowsPassword', true, _('Locked till') . ' ' . $windowsPasswordLockedTime->format('Y-m-d H:i:s'), null, false), true);
|
||||
}
|
||||
if ($is389dsLocked) {
|
||||
$unlockContent->addElement(new htmlImage('../../graphics/security.png'));
|
||||
$unlockContent->addElement(new htmlTableExtendedInputCheckbox('lam_accountStatusUnlock389ds', true, _('Unlock'), null, false), true);
|
||||
|
@ -540,6 +561,10 @@ class user extends baseType {
|
|||
if (isset($_POST['lam_accountStatusUnlockWindows']) && ($_POST['lam_accountStatusUnlockWindows'] == 'on')) {
|
||||
$container->getAccountModule('windowsUser')->setIsDeactivated(false);
|
||||
}
|
||||
// Windows password
|
||||
if (isset($_POST['lam_accountStatusUnlockWindowsPassword']) && ($_POST['lam_accountStatusUnlockWindowsPassword'] == 'on')) {
|
||||
$container->getAccountModule('windowsUser')->unlockPassword();
|
||||
}
|
||||
// 389ds unlocking
|
||||
if (isset($_POST['lam_accountStatusUnlock389ds']) && ($_POST['lam_accountStatusUnlock389ds'] == 'on')) {
|
||||
$container->getAccountModule('locking389ds')->unlock(false);
|
||||
|
@ -869,6 +894,7 @@ class lamUserList extends lamList {
|
|||
$attrs[] = 'sambaAcctFlags';
|
||||
$attrs[] = 'userPassword';
|
||||
$attrs[] = 'userAccountControl';
|
||||
$attrs[] = 'lockoutTime';
|
||||
$attrs[] = 'nsAccountLock';
|
||||
$attrs[] = 'accountUnlockTime';
|
||||
$attrs[] = 'objectClass';
|
||||
|
@ -890,12 +916,13 @@ class lamUserList extends lamList {
|
|||
$sambaLocked = self::isSambaLocked($this->entries[$i]);
|
||||
$ppolicyLocked = self::isPPolicyLocked($this->entries[$i]);
|
||||
$windowsLocked = self::isWindowsLocked($this->entries[$i]);
|
||||
$windowsPasswordLocked = ($this->getWindowsPasswordLockedTime($this->entries[$i]) != null);
|
||||
$is389dsLocked = self::is389dsLocked($this->entries[$i]);
|
||||
$is389dsDeactivated = self::is389dsDeactivated($this->entries[$i]);
|
||||
$hasLocked = ($unixAvailable && $unixLocked)
|
||||
|| ($sambaAvailable && $sambaLocked)
|
||||
|| ($ppolicyAvailable && $ppolicyLocked)
|
||||
|| ($windowsAvailable && $windowsLocked)
|
||||
|| ($windowsAvailable && ($windowsLocked || $windowsPasswordLocked))
|
||||
|| $is389dsDeactivated
|
||||
|| $is389dsLocked;
|
||||
$hasUnlocked = ($unixAvailable && !$unixLocked)
|
||||
|
@ -937,9 +964,13 @@ class lamUserList extends lamList {
|
|||
$sambaLocked = self::isSambaLocked($attrs);
|
||||
$ppolicyLocked = self::isPPolicyLocked($attrs);
|
||||
$windowsLocked = self::isWindowsLocked($attrs);
|
||||
$windowsPasswordLockedTime = $this->getWindowsPasswordLockedTime($attrs);
|
||||
$windowsPasswordLocked = ($windowsPasswordLockedTime != null);
|
||||
$is389dsDeactivated = self::is389dsDeactivated($attrs);
|
||||
$is389dsLocked = self::is389dsLocked($attrs);
|
||||
$partiallyLocked = $unixLocked || $sambaLocked || $ppolicyLocked || $windowsLocked || $is389dsDeactivated || $is389dsLocked;
|
||||
$partiallyLocked = $unixLocked || $sambaLocked
|
||||
|| $ppolicyLocked || $windowsLocked || $windowsPasswordLocked
|
||||
|| $is389dsDeactivated || $is389dsLocked;
|
||||
$fullyLocked = ($unixAvailable || $sambaAvailable || $ppolicyAvailable || $windowsAvailable || $is389dsDeactivated || $is389dsLocked)
|
||||
&& (!$unixAvailable || $unixLocked)
|
||||
&& (!$sambaAvailable || $sambaLocked)
|
||||
|
@ -987,6 +1018,9 @@ class lamUserList extends lamList {
|
|||
}
|
||||
$tipContent .= '<tr><td>' . _('Windows') . ' </td><td><img height=16 width=16 src="../../graphics/' . $windowsIcon . '"></td></tr>';
|
||||
}
|
||||
if ($windowsAvailable && $windowsPasswordLocked) {
|
||||
$tipContent .= '<tr><td>' . _('Locked till') . ' </td><td>' . $windowsPasswordLockedTime->format('Y-m-d H:i:s') . '</td></tr>';
|
||||
}
|
||||
// 389 locked
|
||||
if ($is389dsLocked) {
|
||||
$tipContent .= '<tr><td>' . _('Locked') . ' </td><td><img height=16 width=16 src="../../graphics/lock.png"></td></tr>';
|
||||
|
@ -1083,6 +1117,16 @@ class lamUserList extends lamList {
|
|||
return windowsUser::isDeactivated($attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the Windows password is locked.
|
||||
*
|
||||
* @param array $attrs LDAP attributes
|
||||
* @return DateTime Windows password lock time or null
|
||||
*/
|
||||
public function getWindowsPasswordLockedTime(&$attrs) {
|
||||
return windowsUser::getPasswordLocked($attrs, $this->type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the 389ds is activated.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue