support workstations

This commit is contained in:
Roland Gruber 2020-02-08 15:43:11 +01:00
parent 2fbac1d9f0
commit 7981f59b0e
2 changed files with 163 additions and 2 deletions

View File

@ -2,6 +2,7 @@ March 2020 7.1
- PHP 7 required - PHP 7 required
- Webauthn/FIDO2 support for 2-factor-authentication (requires PHP 7.2) - Webauthn/FIDO2 support for 2-factor-authentication (requires PHP 7.2)
- Personal: support display name (hidden by default in server profile) - Personal: support display name (hidden by default in server profile)
- Windows users: support allowed workstations
- LAM Pro: - LAM Pro:
-> PPolicy: support for password check module -> PPolicy: support for password check module
-> Windows AD LDS support (users and groups) -> Windows AD LDS support (users and groups)

View File

@ -5,7 +5,7 @@ use LAM\ImageUtils\ImageManipulationFactory;
/* /*
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/) This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2013 - 2019 Roland Gruber Copyright (C) 2013 - 2020 Roland Gruber
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -51,6 +51,8 @@ class windowsUser extends baseModule implements passwordService {
private $groupList_orig = array(); private $groupList_orig = array();
/** cache for groups */ /** cache for groups */
private $groupCache = null; private $groupCache = null;
/** host cache to reduce LDAP queries */
private $cachedHostList = null;
/** option for forcing password change, used in postModifyActions */ /** option for forcing password change, used in postModifyActions */
private $pwdLastSet = null; private $pwdLastSet = null;
/** clear text password */ /** clear text password */
@ -117,7 +119,7 @@ class windowsUser extends baseModule implements passwordService {
'pwdLastSet', 'otherMailbox', 'homeDirectory', 'homeDrive', 'msSFU30Name', 'msSFU30NisDomain', 'pwdLastSet', 'pwdLastSet', 'otherMailbox', 'homeDirectory', 'homeDrive', 'msSFU30Name', 'msSFU30NisDomain', 'pwdLastSet',
'lastLogonTimestamp', 'accountExpires', 'jpegPhoto', 'title', 'carLicense', 'employeeNumber', 'employeeType', 'lastLogonTimestamp', 'accountExpires', 'jpegPhoto', 'title', 'carLicense', 'employeeNumber', 'employeeType',
'businessCategory', 'department', 'departmentNumber', 'ou', 'o', 'manager', 'facsimileTelephoneNumber', 'company', 'businessCategory', 'department', 'departmentNumber', 'ou', 'o', 'manager', 'facsimileTelephoneNumber', 'company',
'pager', 'otherPager', 'mobile', 'otherMobile', 'proxyAddresses', 'lockoutTime' 'pager', 'otherPager', 'mobile', 'otherMobile', 'proxyAddresses', 'lockoutTime', 'userWorkstations'
); );
// help Entries // help Entries
$return['help'] = array( $return['help'] = array(
@ -402,6 +404,14 @@ class windowsUser extends baseModule implements passwordService {
"Headline" => _('Exclude from group sync'), "Headline" => _('Exclude from group sync'),
"Text" => _('Enter one group per line that should be ignored when syncing groups.') "Text" => _('Enter one group per line that should be ignored when syncing groups.')
), ),
"userWorkstations" => array(
"Headline" => _("Workstations"), 'attr' => 'userWorkstations',
"Text" => _("List of workstations the user is allowed to login. Empty means every workstation.")
),
"workstations" => array(
"Headline" => _("Workstations"), 'attr' => 'userWorkstations',
"Text" => _("Comma separated list of workstations the user is allowed to login. Empty means every workstation."). ' '. _("Can be left empty.")
),
); );
// upload fields // upload fields
$return['upload_columns'] = array( $return['upload_columns'] = array(
@ -756,6 +766,14 @@ class windowsUser extends baseModule implements passwordService {
'example' => _('uid=smiller,ou=People,dc=company,dc=com'), 'example' => _('uid=smiller,ou=People,dc=company,dc=com'),
); );
} }
if (!$this->isBooleanConfigOptionSet('windowsUser_hideWorkstations')) {
$return['upload_columns'][] = array(
'name' => 'windowsUser_workstations',
'description' => _('Workstations'),
'help' => 'workstations',
'example' => 'PC01,PC02,PC03'
);
}
// profile options // profile options
$profileContainer = new htmlResponsiveRow(); $profileContainer = new htmlResponsiveRow();
$profileContainer->add(new htmlResponsiveInputField(_('Common name'), 'windowsUser_cn', null, 'cn'), 12); $profileContainer->add(new htmlResponsiveInputField(_('Common name'), 'windowsUser_cn', null, 'cn'), 12);
@ -805,6 +823,9 @@ class windowsUser extends baseModule implements passwordService {
'windowsUser_company' => 'company', 'windowsUser_company' => 'company',
'windowsUser_homeDrive' => 'homeDrive' 'windowsUser_homeDrive' => 'homeDrive'
); );
if (!$this->isBooleanConfigOptionSet('windowsUser_hideWorkstations')) {
$return['profile_mappings']['windowsUser_userWorkstations'] = 'userWorkstations';
}
if (!$this->isBooleanConfigOptionSet('windowsUser_hidemsSFU30NisDomain', true)) { if (!$this->isBooleanConfigOptionSet('windowsUser_hidemsSFU30NisDomain', true)) {
$return['profile_mappings']['windowsUser_msSFU30NisDomain'] = 'msSFU30NisDomain'; $return['profile_mappings']['windowsUser_msSFU30NisDomain'] = 'msSFU30NisDomain';
} }
@ -867,6 +888,9 @@ class windowsUser extends baseModule implements passwordService {
'homeDirectory' => _('Home directory'), 'homeDirectory' => _('Home directory'),
'accountExpires' => _('Account expiration date'), 'accountExpires' => _('Account expiration date'),
); );
if (!$this->isBooleanConfigOptionSet('windowsUser_hideWorkstations')) {
$return['PDF_fields']['userWorkstations'] = _('Workstations');
}
if (!$this->isBooleanConfigOptionSet('windowsUser_hideproxyAddresses', true)) { if (!$this->isBooleanConfigOptionSet('windowsUser_hideproxyAddresses', true)) {
$return['PDF_fields']['proxyAddresses'] = _('Proxy-Addresses'); $return['PDF_fields']['proxyAddresses'] = _('Proxy-Addresses');
} }
@ -1043,6 +1067,8 @@ class windowsUser extends baseModule implements passwordService {
$this->messages['file'][1] = array('ERROR', _('Please upload a .jpg/.jpeg file.')); $this->messages['file'][1] = array('ERROR', _('Please upload a .jpg/.jpeg file.'));
$this->messages['file'][2] = array('ERROR', _('Unable to process this file.')); $this->messages['file'][2] = array('ERROR', _('Unable to process this file.'));
$this->messages['file'][3] = array('ERROR', _('File is too large. Maximum allowed size is %s kB.')); $this->messages['file'][3] = array('ERROR', _('File is too large. Maximum allowed size is %s kB.'));
$this->messages['workstations'][0] = array('ERROR', _('Workstations'), _('Please enter a comma separated list of host names!'));
$this->messages['workstations'][1] = array('ERROR', _('Account %s:') . ' windowsUser_workstations', _('Please enter a comma separated list of host names!'));
} }
/** /**
@ -1250,6 +1276,14 @@ class windowsUser extends baseModule implements passwordService {
$lastLogonTimestampGroup->addElement(new htmlHelpLink('lastLogonTimestamp')); $lastLogonTimestampGroup->addElement(new htmlHelpLink('lastLogonTimestamp'));
$containerLeft->addField($lastLogonTimestampGroup); $containerLeft->addField($lastLogonTimestampGroup);
} }
if (!$this->isBooleanConfigOptionSet('windowsUser_hideWorkstations')) {
$containerLeft->addLabel(new htmlOutputText(_('Workstations')));
$userWorkstationsGroup = new htmlGroup();
$userWorkstationsGroup->addElement(new htmlAccountPageButton(get_class($this), 'userWorkstations', 'open', _('Edit workstations')));
$userWorkstationsGroup->addElement(new htmlSpacer('0.5rem', null));
$userWorkstationsGroup->addElement(new htmlHelpLink('userWorkstations'));
$containerLeft->addField($userWorkstationsGroup);
}
// user profile area // user profile area
$containerLeft->add(new htmlSubTitle(_('User profile')), 12); $containerLeft->add(new htmlSubTitle(_('User profile')), 12);
// profile path // profile path
@ -2128,6 +2162,123 @@ class windowsUser extends baseModule implements passwordService {
return $return; return $return;
} }
/**
* This function will create the HTML page to edit the allowed workstations.
*
* @return htmlElement meta HTML code
*/
function display_html_userWorkstations() {
$return = new htmlResponsiveRow();
if ($this->get_scope()=='user') {
// Get list of all hosts.
$userWorkstations = array();
$availableUserWorkstations = array();
$result = $this->getHostList();
foreach ($result as $host) {
$availableUserWorkstations[] = str_replace("$", '', $host);
}
sort($availableUserWorkstations, SORT_STRING);
if (isset($this->attributes['userWorkstations'][0])) {
$wsAttr = str_replace(' ', '', $this->attributes['userWorkstations'][0]);
$userWorkstations = explode (',', $wsAttr);
}
$availableUserWorkstations = array_delete($userWorkstations, $availableUserWorkstations);
$return->add(new htmlSubTitle(_("Allowed workstations")), 12);
$userWorkstationsOptions = array();
foreach ($userWorkstations as $userWorkstation) {
$userWorkstationsOptions[$userWorkstation] = $userWorkstation;
}
$availableUserWorkstationsOptions = array();
foreach ($availableUserWorkstations as $availableUserWorkstation) {
$availableUserWorkstationsOptions[$availableUserWorkstation] = $availableUserWorkstation;
}
$this->addDoubleSelectionArea($return, _("Allowed workstations"), _("Available workstations"), $userWorkstationsOptions, array(), $availableUserWorkstationsOptions, array(), 'workstations', false, true);
$return->addVerticalSpacer('2rem');
$backButton = new htmlAccountPageButton(get_class($this), 'attributes', 'back', _('Back'));
$return->add($backButton, 12);
}
return $return;
}
/**
* Processes user input of the workstation page.
* It checks if all input values are correct and updates the associated LDAP attributes.
*
* @return array list of info/error messages
*/
function process_userWorkstations() {
// Load attributes
if (isset($_POST['workstations_2']) && isset($_POST['workstations_left'])) { // Add workstations to list
$workstations = array();
if (isset($this->attributes['userWorkstations'][0])) {
$temp = str_replace(' ', '', $this->attributes['userWorkstations'][0]);
$workstations = explode (',', $temp);
for ($i=0; $i<count($workstations); $i++) {
if ($workstations[$i]=='') {
unset($workstations[$i]);
}
}
$workstations = array_values($workstations);
}
// Add new // Add workstations
$workstations = array_merge($workstations, $_POST['workstations_2']);
// remove doubles
$workstations = array_flip($workstations);
$workstations = array_unique($workstations);
$workstations = array_flip($workstations);
// sort workstations
sort($workstations);
// Recreate workstation string
$this->attributes['userWorkstations'][0] = $workstations[0];
for ($i=1; $i<count($workstations); $i++) {
$this->attributes['userWorkstations'][0] = $this->attributes['userWorkstations'][0] . "," . $workstations[$i];
}
}
elseif (isset($_POST['workstations_1']) && isset($_POST['workstations_right'])) { // remove // Add workstations from list
// Put all workstations in array
$temp = str_replace(' ', '', $this->attributes['userWorkstations'][0]);
$workstations = explode (',', $temp);
for ($i=0; $i<count($workstations); $i++) {
if ($workstations[$i]=='') {
unset($workstations[$i]);
}
}
$workstations = array_values($workstations);
// Remove unwanted workstations from array
$workstations = array_delete($_POST['workstations_1'], $workstations);
// Recreate workstation string
unset($this->attributes['userWorkstations'][0]);
if (sizeof($workstations) > 0) {
$this->attributes['userWorkstations'][0] = $workstations[0];
for ($i=1; $i<count($workstations); $i++) {
$this->attributes['userWorkstations'][0] = $this->attributes['userWorkstations'][0] . "," . $workstations[$i];
}
}
}
return array();
}
/**
* Returns a list of existing hosts.
*
* @return array host names
*/
private function getHostList() {
if ($this->cachedHostList != null) {
return $this->cachedHostList;
}
$this->cachedHostList = searchLDAPByAttribute('cn', '*', 'computer', array('cn'), array('host'));
for ($i = 0; $i < sizeof($this->cachedHostList); $i++) {
$this->cachedHostList[$i] = $this->cachedHostList[$i]['cn'][0];
}
return $this->cachedHostList;
}
/** /**
* Runs the postmodify actions. * Runs the postmodify actions.
* *
@ -2474,6 +2625,9 @@ class windowsUser extends baseModule implements passwordService {
$errors[] = $errMsg; $errors[] = $errMsg;
} }
} }
// workstations
$this->mapSimpleUploadField($rawAccounts, $ids, $partialAccounts, $i, 'windowsUser_workstations', 'userWorkstations',
'workstations', $this->messages['workstations'][1], $errors);
// groups // groups
if (isset($ids['windowsUser_groups']) && ($rawAccounts[$i][$ids['windowsUser_groups']] != "")) { if (isset($ids['windowsUser_groups']) && ($rawAccounts[$i][$ids['windowsUser_groups']] != "")) {
$valueList = preg_split('/;[ ]*/', $rawAccounts[$i][$ids['windowsUser_groups']]); $valueList = preg_split('/;[ ]*/', $rawAccounts[$i][$ids['windowsUser_groups']]);
@ -2720,6 +2874,7 @@ class windowsUser extends baseModule implements passwordService {
$this->addSimplePDFField($return, 'ou', _('Organisational unit')); $this->addSimplePDFField($return, 'ou', _('Organisational unit'));
$this->addSimplePDFField($return, 'o', _('Organisation')); $this->addSimplePDFField($return, 'o', _('Organisation'));
$this->addSimplePDFField($return, 'manager', _('Manager')); $this->addSimplePDFField($return, 'manager', _('Manager'));
$this->addSimplePDFField($return, 'userWorkstations', _('Workstations'));
$deactivated = _('no'); $deactivated = _('no');
if ($this->isDeactivated($this->attributes)) { if ($this->isDeactivated($this->attributes)) {
$deactivated = _('yes'); $deactivated = _('yes');
@ -2793,6 +2948,10 @@ class windowsUser extends baseModule implements passwordService {
// force password change // force password change
$passwordChangeCheckbox = new htmlResponsiveInputCheckbox('windowsUser_pwdMustChange', true, _('Password change at next login'), 'pwdMustChange'); $passwordChangeCheckbox = new htmlResponsiveInputCheckbox('windowsUser_pwdMustChange', true, _('Password change at next login'), 'pwdMustChange');
$return->add($passwordChangeCheckbox, 12); $return->add($passwordChangeCheckbox, 12);
if (!$this->isBooleanConfigOptionSet('windowsUser_hideWorkstations')) {
// allowed workstations
$return->add(new htmlResponsiveInputField(_('Workstations'), 'windowsUser_userWorkstations', '', 'workstations'), 12);
}
return $return; return $return;
} }
@ -3532,6 +3691,7 @@ class windowsUser extends baseModule implements passwordService {
$configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hidemsSFU30NisDomain', true, _('NIS domain'), null, true), 12, 4); $configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hidemsSFU30NisDomain', true, _('NIS domain'), null, true), 12, 4);
$configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hidepwdLastSet', false, _('Last password change'), null, true), 12, 4); $configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hidepwdLastSet', false, _('Last password change'), null, true), 12, 4);
$configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hidelastLogonTimestamp', false, _('Last login'), null, true), 12, 4); $configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hidelastLogonTimestamp', false, _('Last login'), null, true), 12, 4);
$configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hideWorkstations', false, _('Workstations'), null, true), 12, 4);
$configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hidejpegPhoto', true, _('Photo'), null, true), 12, 4); $configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hidejpegPhoto', true, _('Photo'), null, true), 12, 4);
$configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hidetitle', true, _('Job title'), null, true), 12, 4); $configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hidetitle', true, _('Job title'), null, true), 12, 4);
$configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hidecarLicense', true, _('Car license'), null, true), 12, 4); $configContainer->add(new htmlResponsiveInputCheckbox('windowsUser_hidecarLicense', true, _('Car license'), null, true), 12, 4);