LDAPAccountManager/lam/lib/modules/windowsUser.inc

871 lines
35 KiB
PHP
Raw Normal View History

2013-04-06 15:00:53 +00:00
<?php
/*
$Id$
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2013 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
*/
/**
* Manages Windows AD (e.g. Samba 4) users.
*
* @package modules
* @author Roland Gruber
*/
/**
* Manages Windows AD (e.g. Samba 4) users.
*
* @package modules
*/
2013-04-07 17:28:09 +00:00
class windowsUser extends baseModule implements passwordService {
2013-04-06 15:00:53 +00:00
/** initial account flags */
const DEFAULT_ACCOUNT_CONTROL = 0x00000200;
/** password never expires */
const AC_PWD_NEVER_EXPIRES = 0x00010000;
/** login requires smartcard */
const AC_SMARTCARD_REQUIRED = 0x00040000;
/** account is disabled */
const AC_ACCOUNT_DISABLED = 0x00000002;
/** currently locked out, read only flag */
const AC_LOCKED_OUT = 0x00000010;
/** current group of names list */
private $groupList = array();
/** original group of names list */
private $groupList_orig = array();
/** cache for groups */
private $groupCache = null;
2013-04-06 15:00:53 +00:00
/**
* Returns meta data that is interpreted by parent class
*
* @return array array with meta data
*
* @see baseModule::get_metaData()
*/
public function get_metaData() {
$return = array();
// icon
$return['icon'] = 'samba.png';
// manages user accounts
$return["account_types"] = array('user');
// this is a base module
$return["is_base"] = true;
2013-04-07 17:28:09 +00:00
// PHP extensions
$return['extensions'] = array('iconv');
2013-04-06 15:00:53 +00:00
// RDN attribute
$return["RDN"] = array("cn" => "high");
// LDAP filter
$return["ldap_filter"] = array('and' => '(!(objectClass=computer))', 'or' => "(objectClass=user)");
2013-04-06 15:00:53 +00:00
// alias name
$return["alias"] = _("Windows");
// module dependencies
$return['dependencies'] = array('depends' => array(), 'conflicts' => array());
// managed object classes
$return['objectClasses'] = array('user');
// managed attributes
$return['attributes'] = array('cn', 'sAMAccountName', 'description', 'displayName', 'givenName', 'initials',
'l', 'mail', 'otherTelephone', 'physicalDeliveryOfficeName', 'postalCode', 'postOfficeBox', 'sn', 'st',
'streetAddress', 'telephoneNumber', 'url', 'wWWHomePage', 'userAccountControl', 'profilePath', 'scriptPath',
'pwdLastSet');
2013-04-06 15:00:53 +00:00
// help Entries
$return['help'] = array(
'cn' => array(
"Headline" => _('User name'), 'attr' => 'cn, sAMAccountName',
"Text" => _('Please enter the user\'s name.')
),
'description' => array(
"Headline" => _('Description'), 'attr' => 'description',
"Text" => _('Please enter a descriptive text for this user.')
),
'displayName' => array(
"Headline" => _('Display name'), 'attr' => 'displayName',
"Text" => _('This is the account\'s full name on Windows systems.')
),
'givenName' => array(
"Headline" => _('First name'), 'attr' => 'givenName',
"Text" => _('First name of user. Only letters, - and spaces are allowed.')
),
'initials' => array(
"Headline" => _('Initials'), 'attr' => 'initials',
"Text" => _('The initials of the user\'s first names.')
),
'l' => array(
"Headline" => _('Location'), 'attr' => 'l',
"Text" => _('This describes the location of the user.')
),
'mail' => array(
"Headline" => _('Email address'), 'attr' => 'mail',
"Text" => _('The user\'s email address.')
),
'otherTelephone' => array(
"Headline" => _('Other telephone numbers'), 'attr' => 'otherTelephone',
"Text" => _('If the user has multiple telephone numbers then please enter it here.')
),
'physicalDeliveryOfficeName' => array(
"Headline" => _('Office name'), 'attr' => 'physicalDeliveryOfficeName',
"Text" => _('The office name of the user (e.g. YourCompany, Human Resources).')
),
'postalCode' => array(
"Headline" => _('Postal code'), 'attr' => 'postalCode',
"Text" => _('The postal code of the user\'s address.')
),
'postOfficeBox' => array(
"Headline" => _('Post office box'), 'attr' => 'postOfficeBox',
"Text" => _('The post office box of the user\'s address.')
),
'sn' => array(
"Headline" => _('Last name'), 'attr' => 'sn',
"Text" => _('Last name of user. Only letters, - and spaces are allowed.')
),
'st' => array(
"Headline" => _('State'), 'attr' => 'st',
"Text" => _('The state where the user resides or works.')
),
'streetAddress' => array(
"Headline" => _('Street'), 'attr' => 'streetAddress',
"Text" => _('The street name of the user\'s address.')
),
'telephoneNumber' => array(
"Headline" => _('Telephone number'), 'attr' => 'telephoneNumber',
"Text" => _('The user\'s telephone number.')
),
'url' => array(
"Headline" => _('Other web sites'), 'attr' => 'url',
"Text" => _('Here you can enter additional web sites for the user.')
),
'wWWHomePage' => array(
"Headline" => _('Web site'), 'attr' => 'wWWHomePage',
"Text" => _('The user\'s web site (e.g. http://www.company.com).')
),
"deactivated" => array(
"Headline" => _("Account is deactivated"),
"Text" => _("If checked then the account will be deactivated.")),
"locked" => array(
"Headline" => _("Account is locked"),
"Text" => _("If checked then the account is locked. You may only unlock accounts but not lock them.")),
"noExpire" => array(
"Headline" => _("Password does not expire"),
"Text" => _("If checked password does not expire.")),
"requireCard" => array(
"Headline" => _("Require smartcard"),
"Text" => _("The user must log on using a smart card.")),
"runLogonScript" => array(
"Headline" => _("Run logon script"),
"Text" => _("The logon script is executed.")),
"profilePath" => array(
"Headline" => _("Profile path"), 'attr' => 'profilePath',
"Text" => _('Path of the user profile (UNC-path, e.g. \\\\server\\share\\user). $user is replaced with user name.'). ' '. _("Can be left empty.")),
"scriptPath" => array(
"Headline" => _("Logon script"), 'attr' => 'scriptPath',
"Text" => _('File name and path relative to netlogon-share which should be executed on logon. $user is replaced with user name.'). ' '. _("Can be left empty.")),
"pwdMustChange" => array ("Headline" => _("Password change at next login"),
"Text" => _("If you set this option then the user has to change his password at the next login.")),
);
2013-04-06 15:00:53 +00:00
// upload fields
$return['upload_columns'] = array(
array(
2013-04-07 17:28:09 +00:00
'name' => 'windowsUser_name',
'description' => _('User name'),
2013-04-06 15:00:53 +00:00
'help' => 'cn',
2013-04-07 17:28:09 +00:00
'example' => _('smiller'),
2013-04-06 15:00:53 +00:00
'required' => true
),
array(
2013-04-07 17:28:09 +00:00
'name' => 'windowsUser_description',
2013-04-06 15:00:53 +00:00
'description' => _('Description'),
'help' => 'description',
),
array(
2013-04-07 17:28:09 +00:00
'name' => 'windowsUser_l',
2013-04-06 15:00:53 +00:00
'description' => _('Location'),
2013-04-07 17:28:09 +00:00
'help' => 'l',
2013-04-06 15:00:53 +00:00
'example' => _('MyCity'),
),
);
// available PDF fields
$return['PDF_fields'] = array(
'cn' => _('User name'),
'description' => _('Description'),
'displayName' => _('Display name'),
'givenName' => _('First name'),
'initials' => _('Initials'),
'l' => _('Location'),
'mail' => _('Email address'),
'otherTelephone' => _('Other telephone numbers'),
'physicalDeliveryOfficeName' => _('Office name'),
'postalCode' => _('Postal code'),
'postOfficeBox' => _('Post office box'),
'sn' => _('Last name'),
'st' => _('State'),
'streetAddress' => _('Street'),
'telephoneNumber' => _('Telephone number'),
'url' => _('Other web sites'),
'wWWHomePage' => _('Web site'),
);
return $return;
}
/**
* Initializes the module after it became part of an accountContainer
*
* @param string $base the name of the accountContainer object ($_SESSION[$base])
*/
function init($base) {
// call parent init
parent::init($base);
$this->groupList = array();
$this->groupList_orig = array();
}
2013-04-06 15:00:53 +00:00
/**
* This function fills the $messages variable with output messages from this module.
*/
public function load_Messages() {
$this->messages['cn'][0] = array('ERROR', _('User name'), _('User name contains invalid characters. Valid characters are: a-z, A-Z, 0-9 and .-_ !'));
$this->messages['cn'][1] = array('ERROR', _('Account %s:') . ' windowsUser_cn', _('User name contains invalid characters. Valid characters are: a-z, A-Z, 0-9 and .-_ !'));
$this->messages['displayName'][0] = array('ERROR', _('Display name'), _('Please enter a valid display name!'));
$this->messages['displayName'][1] = array('ERROR', _('Account %s:') . ' windowsUser_displayName', _('Please enter a valid display name!'));
$this->messages['givenName'][0] = array('ERROR', _('First name'), _('First name contains invalid characters!'));
$this->messages['givenName'][1] = array('ERROR', _('Account %s:') . ' windowsUser_givenName', _('First name contains invalid characters!'));
$this->messages['sn'][0] = array('ERROR', _('Last name'), _('Last name contains invalid characters or is empty!'));
$this->messages['sn'][1] = array('ERROR', _('Account %s:') . ' windowsUser_sn', _('Last name contains invalid characters or is empty!'));
$this->messages['telephoneNumber'][0] = array('ERROR', _('Telephone number'), _('Please enter a valid telephone number!'));
$this->messages['telephoneNumber'][1] = array('ERROR', _('Account %s:') . ' windowsUser_telephone', _('Please enter a valid telephone number!'));
$this->messages['otherTelephone'][0] = array('ERROR', _('Other telephone numbers'), _('Please enter a valid telephone number!'));
$this->messages['otherTelephone'][1] = array('ERROR', _('Account %s:') . ' windowsUser_otherTelephone', _('Please enter a valid telephone number!'));
$this->messages['postalCode'][0] = array('ERROR', _('Postal code'), _('Please enter a valid postal code!'));
$this->messages['postalCode'][1] = array('ERROR', _('Account %s:') . ' windowsUser_postalCode', _('Please enter a valid postal code!'));
$this->messages['mail'][0] = array('ERROR', _('Email address'), _('Please enter a valid email address!'));
$this->messages['mail'][1] = array('ERROR', _('Account %s:') . ' windowsUser_mail', _('Please enter a valid email address!'));
$this->messages['profilePath'][0] = array('ERROR', _('Profile path'), _('Profile path is invalid!'));
$this->messages['profilePath'][1] = array('ERROR', _('Account %s:') . ' windowsUser_profilePath', _('Profile path is invalid!'));
$this->messages['scriptPath'][0] = array('ERROR', _('Logon script'), _('Logon script is invalid!'));
$this->messages['scriptPath'][1] = array('ERROR', _('Account %s:') . ' windowsUser_scriptPath', _('Logon script is invalid!'));
}
/**
* This function loads all needed LDAP attributes.
*
* @param array $attr list of attributes
*/
function load_attributes($attr) {
parent::load_attributes($attr);
// get group memberships
$groupList = searchLDAPByAttribute('member', $this->getAccountContainer()->dn_orig, 'group', array('dn'), array('group'));
$this->groupList_orig = array();
for ($i = 0; $i < sizeof($groupList); $i++) {
$this->groupList_orig[] = $groupList[$i]['dn'];
}
$this->groupList_orig = array_values(array_unique($this->groupList_orig));
$this->groupList = $this->groupList_orig;
2013-04-06 15:00:53 +00:00
}
/**
* Returns the HTML meta data for the main account page.
*
* @return htmlElement HTML meta data
*/
public function display_html_attributes() {
$containerLeft = new htmlTable();
$containerLeft->alignment = htmlElement::ALIGN_TOP;
if ($this->getAccountContainer()->isNewAccount && !isset($this->attributes['userAccountControl'][0])) {
$this->attributes['userAccountControl'][0] = windowsUser::DEFAULT_ACCOUNT_CONTROL;
}
$containerLeft->addElement(new htmlSubTitle(_('General')), true);
$this->addSimpleInputTextField($containerLeft, 'cn', _('User name'), true);
$this->addSimpleInputTextField($containerLeft, 'givenName', _('First name'));
$this->addSimpleInputTextField($containerLeft, 'sn', _('Last name'));
$this->addSimpleInputTextField($containerLeft, 'displayName', _('Display name'));
$this->addSimpleInputTextField($containerLeft, 'initials', _('Initials'));
$this->addSimpleInputTextField($containerLeft, 'description', _('Description'));
$containerLeft->addElement(new htmlSubTitle(_('Address')), true);
$this->addSimpleInputTextField($containerLeft, 'streetAddress', _('Street'), false, 20, true);
$this->addSimpleInputTextField($containerLeft, 'postOfficeBox', _('Post office box'));
$this->addSimpleInputTextField($containerLeft, 'postalCode', _('Postal code'));
$this->addSimpleInputTextField($containerLeft, 'l', _('Location'));
$this->addSimpleInputTextField($containerLeft, 'st', _('State'));
$this->addSimpleInputTextField($containerLeft, 'physicalDeliveryOfficeName', _('Office name'));
$containerLeft->addElement(new htmlSubTitle(_('Contact data')), true);
$this->addSimpleInputTextField($containerLeft, 'mail', _('Email address'));
$this->addSimpleInputTextField($containerLeft, 'telephoneNumber', _('Telephone number'));
$this->addMultiValueInputTextField($containerLeft, 'otherTelephone', _('Other telephone numbers'));
$this->addSimpleInputTextField($containerLeft, 'wWWHomePage', _('Web site'));
$this->addMultiValueInputTextField($containerLeft, 'url', _('Other web sites'));
2013-04-06 15:00:53 +00:00
$containerLeft->addElement(new htmlSubTitle(_('Options')), true);
// locked out
$containerLeft->addElement(new htmlOutputText(_("Account is locked")));
$lockedOut = windowsUser::isLockedOut($this->attributes);
$lockedOutCheckbox = new htmlInputCheckbox('lockedOut', $lockedOut);
$lockedOutCheckbox->setIsEnabled(false);
$lockedOutGroup = new htmlGroup();
$lockedOutGroup->addElement($lockedOutCheckbox);
if ($lockedOut) {
$lockedOutGroup->addElement(new htmlButton('unlock', _('Unlock')));
}
$containerLeft->addElement($lockedOutGroup);
$containerLeft->addElement(new htmlHelpLink('locked'), true);
// password change required
$pwdMustChange = false;
if (isset($this->attributes['pwdLastSet'][0]) && ($this->attributes['pwdLastSet'][0] === '0')) {
$pwdMustChange = true;
}
$containerLeft->addElement(new htmlTableExtendedInputCheckbox('pwdMustChange', $pwdMustChange, _("User must change password"), 'pwdMustChange'), true);
// deactivated
$deactivated = windowsUser::isDeactivated($this->attributes);
$containerLeft->addElement(new htmlTableExtendedInputCheckbox('deactivated', $deactivated, _("Account is deactivated"), 'deactivated'), true);
// password does not expire
$noExpire = windowsUser::isNeverExpiring($this->attributes);
$containerLeft->addElement(new htmlTableExtendedInputCheckbox('noExpire', $noExpire, _("Password does not expire"), 'noExpire'), true);
// require smartcard
$requireCard = windowsUser::isSmartCardRequired($this->attributes);
$containerLeft->addElement(new htmlTableExtendedInputCheckbox('requireCard', $requireCard, _("Require smartcard"), 'requireCard'), true);
$containerLeft->addElement(new htmlSubTitle(_('User profile')), true);
// profile path
$this->addSimpleInputTextField($containerLeft, 'profilePath', _('Profile path'));
// logon script
$this->addSimpleInputTextField($containerLeft, 'scriptPath', _('Logon script'));
$containerLeft->addElement(new htmlEqualWidth(array('streetAddress', 'cn')));
$containerRight = new htmlTable();
$containerRight->alignment = htmlElement::ALIGN_TOP;
$containerRight->addElement(new htmlSubTitle(_('Groups')), true);
$containerRight->addElement(new htmlAccountPageButton(get_class($this), 'group', 'edit', _('Edit groups')), true);
$containerRight->addElement(new htmlSpacer(null, '10px'), true);
$groupsList = new htmlGroup();
$groupCNs = array();
for ($i = 0; $i < sizeof($this->groupList); $i++) {
$groupCNs[] = extractRDNValue($this->groupList[$i]);
}
natcasesort($groupCNs);
foreach ($groupCNs as $cn) {
$groupsList->addElement(new htmlOutputText($cn));
$groupsList->addElement(new htmlOutputText('<br>', false));
}
$containerRight->addElement($groupsList);
$container = new htmlTable();
$container->addElement($containerLeft);
$container->addElement(new htmlSpacer('40px', null));
$container->addElement($containerRight);
2013-04-06 15:00:53 +00:00
return $container;
}
/**
* Processes user input of the primary module page.
* It checks if all input values are correct and updates the associated LDAP attributes.
*
* @return array list of info/error messages
*/
public function process_attributes() {
$return = array();
// cn
$this->attributes['cn'][0] = $_POST['cn'];
$this->attributes['sAMAccountName'][0] = $_POST['cn'];
if (!get_preg($_POST['cn'], 'username')) {
$return[] = $this->messages['cn'][0];
}
// description
$this->attributes['description'][0] = $_POST['description'];
// display name
$this->attributes['displayName'][0] = $_POST['displayName'];
if (!empty($this->attributes['displayName'][0]) && !get_preg($_POST['displayName'], 'realname')) {
$return[] = $this->messages['displayName'][0];
}
// first name
$this->attributes['givenName'][0] = $_POST['givenName'];
if (!empty($this->attributes['givenName'][0]) && !get_preg($_POST['givenName'], 'realname')) {
$return[] = $this->messages['givenName'][0];
}
// initials
$this->attributes['initials'][0] = $_POST['initials'];
// location
$this->attributes['l'][0] = $_POST['l'];
// email
$this->attributes['mail'][0] = $_POST['mail'];
if (!empty($this->attributes['mail'][0]) && !get_preg($_POST['mail'], 'email')) {
$return[] = $this->messages['mail'][0];
}
// other telephones
$this->processMultiValueInputTextField('otherTelephone', $return, 'telephone');
// office name
$this->attributes['physicalDeliveryOfficeName'][0] = $_POST['physicalDeliveryOfficeName'];
// postal code
$this->attributes['postalCode'][0] = $_POST['postalCode'];
if (!get_preg($_POST['postalCode'], 'postalCode')) {
$return[] = $this->messages['postalCode'][0];
}
// post office box
$this->attributes['postOfficeBox'][0] = $_POST['postOfficeBox'];
// last name
$this->attributes['sn'][0] = $_POST['sn'];
if (!empty($this->attributes['sn'][0]) && !get_preg($_POST['sn'], 'realname')) {
$return[] = $this->messages['sn'][0];
}
// state
$this->attributes['st'][0] = $_POST['st'];
// street
$this->attributes['streetAddress'][0] = $_POST['streetAddress'];
// telephone
$this->attributes['telephoneNumber'][0] = $_POST['telephoneNumber'];
if (!get_preg($_POST['telephoneNumber'], 'telephone')) {
$return[] = $this->messages['telephoneNumber'][0];
}
// other web sites
$this->processMultiValueInputTextField('url', $return);
// web site
$this->attributes['wWWHomePage'][0] = $_POST['wWWHomePage'];
// password must be changed
if (isset($_POST['pwdMustChange']) && ($_POST['pwdMustChange'] == 'on')) {
$this->attributes['pwdLastSet'][0] = '0';
}
else {
if (isset($this->orig['pwdLastSet'][0]) && ($this->orig['pwdLastSet'][0] !== '0')) {
$this->attributes['pwdLastSet'][0] = $this->orig['pwdLastSet'][0];
}
else {
$this->attributes['pwdLastSet'][0] = '-1';
}
}
// deactivated
$deactivated = isset($_POST['deactivated']) && ($_POST['deactivated'] == 'on');
windowsUser::setIsDeactivated($this->attributes, $deactivated);
// no expire
$noExpire = isset($_POST['noExpire']) && ($_POST['noExpire'] == 'on');
windowsUser::setIsNeverExpiring($this->attributes, $noExpire);
// smartcard required
$requireCard = isset($_POST['requireCard']) && ($_POST['requireCard'] == 'on');
windowsUser::setIsSmartCardRequired($this->attributes, $requireCard);
// profile path
$this->attributes['profilePath'][0] = $_POST['profilePath'];
$this->attributes['profilePath'][0] = str_replace('$user', $this->attributes['cn'][0], $this->attributes['profilePath'][0]);
if (!($this->attributes['profilePath'][0] == '') && !get_preg($this->attributes['profilePath'][0], 'UNC')) {
$return[] = $this->messages['profilePath'][0];
}
// logon script
$this->attributes['scriptPath'][0] = $_POST['scriptPath'];
$this->attributes['scriptPath'][0] = str_replace('$user', $this->attributes['cn'][0], $this->attributes['scriptPath'][0]);
if (($this->attributes['scriptPath'][0] != '') && (!get_preg($this->attributes['scriptPath'][0], 'logonscript'))) {
$return[] = $this->messages['scriptPath'][0];
2013-04-07 17:28:09 +00:00
}
2013-04-06 15:00:53 +00:00
return $return;
}
/**
* Displays the group selection.
*
* @return htmlElement meta HTML code
*/
function display_html_group() {
$return = new htmlTable();
$groups = $this->findGroups();
// sort by DN
usort($groups, 'compareDN');
$groupContainer = new htmlTable();
$groupContainer->alignment = htmlElement::ALIGN_TOP;
$groupContainer->addElement(new htmlSubTitle(_("Groups of names")), true);
$groupContainer->addElement(new htmlOutputText(_("Selected groups")));
$groupContainer->addElement(new htmlOutputText(''));
$groupContainer->addElement(new htmlOutputText(_("Available groups")));
$groupContainer->addNewLine();
$selectedGroups = array();
// sort by DN
usort($this->groupList, 'compareDN');
for ($i = 0; $i < sizeof($this->groupList); $i++) {
if (in_array($this->groupList[$i], $groups)) {
$selectedGroups[getAbstractDN($this->groupList[$i])] = $this->groupList[$i];
}
}
$availableGroups = array();
foreach ($groups as $dn) {
if (!in_array($dn, $this->groupList)) {
$availableGroups[getAbstractDN($dn)] = $dn;
}
}
$remGroupSelect = new htmlSelect('removegroups', $selectedGroups, null, 15);
$remGroupSelect->setMultiSelect(true);
$remGroupSelect->setTransformSingleSelect(false);
$remGroupSelect->setHasDescriptiveElements(true);
$remGroupSelect->setRightToLeftTextDirection(true);
$remGroupSelect->setSortElements(false);
$groupContainer->addElement($remGroupSelect);
$buttonGroupContainer = new htmlTable();
$buttonGroupContainer->addElement(new htmlButton('addgroups_button', 'back.gif', true), true);
$buttonGroupContainer->addElement(new htmlButton('removegroups_button', 'forward.gif', true), true);
$buttonGroupContainer->addElement(new htmlHelpLink('addgroup'));
$groupContainer->addElement($buttonGroupContainer);
$addGroupSelect = new htmlSelect('addgroups', $availableGroups, null, 15);
$addGroupSelect->setMultiSelect(true);
$addGroupSelect->setHasDescriptiveElements(true);
$addGroupSelect->setTransformSingleSelect(false);
$addGroupSelect->setRightToLeftTextDirection(true);
$addGroupSelect->setSortElements(false);
$groupContainer->addElement($addGroupSelect);
$groupContainer->addNewLine();
$return->addElement($groupContainer);
$return->addNewLine();
$backGroup = new htmlGroup();
$backGroup->colspan = 10;
$backGroup->addElement(new htmlSpacer(null, '10px'), true);
$backButton = new htmlAccountPageButton(get_class($this), 'attributes', 'back', _('Back'));
$backGroup->addElement($backButton);
$return->addElement($backGroup);
return $return;
}
/**
* Processes user input of the group selection page.
* It checks if all input values are correct and updates the associated LDAP attributes.
*
* @return array list of info/error messages
*/
function process_group() {
if (isset($_POST['addgroups']) && isset($_POST['addgroups_button'])) { // Add groups to list
// add new group
$this->groupList = @array_merge($this->groupList, $_POST['addgroups']);
}
elseif (isset($_POST['removegroups']) && isset($_POST['removegroups_button'])) { // remove groups from list
$this->groupList = array_delete($_POST['removegroups'], $this->groupList);
}
return array();
}
/**
* Runs the postmodify actions.
*
* @see baseModule::postModifyActions()
*
* @param boolean $newAccount
* @param array $attributes LDAP attributes of this entry
* @return array array which contains status messages. Each entry is an array containing the status message parameters.
*/
public function postModifyActions($newAccount, $attributes) {
$messages = array();
// set groups
$groups = $this->findGroups();
$toAdd = array_values(array_diff($this->groupList, $this->groupList_orig));
$toRem = array_values(array_diff($this->groupList_orig, $this->groupList));
$toUpdate = array_values(array_intersect($this->groupList, $this->groupList_orig));
$ldapUser = $_SESSION['ldap']->decrypt_login();
$ldapUser = $ldapUser[0];
// add groups
for ($i = 0; $i < sizeof($toAdd); $i++) {
if (in_array($toAdd[$i], $groups)) {
$success = @ldap_mod_add($_SESSION['ldap']->server(), $toAdd[$i], array('member' => array($this->getAccountContainer()->finalDN)));
if (!$success) {
logNewMessage(LOG_ERR, '[' . $ldapUser .'] Unable to add user ' . $this->getAccountContainer()->finalDN . ' to group: ' . $toAdd[$i] . ' (' . ldap_err2str(ldap_errno($_SESSION['ldap']->server())) . ').');
$messages[] = array('ERROR', sprintf(_('Was unable to add attributes to DN: %s.'), $toAdd[$i]), ldap_error($_SESSION['ldap']->server()));
}
else {
logNewMessage(LOG_NOTICE, '[' . $ldapUser .'] Added user ' . $this->getAccountContainer()->finalDN . ' to group: ' . $toAdd[$i]);
}
}
}
// remove groups
for ($i = 0; $i < sizeof($toRem); $i++) {
if (in_array($toRem[$i], $groups)) {
$success = @ldap_mod_del($_SESSION['ldap']->server(), $toRem[$i], array('member' => array($this->getAccountContainer()->dn_orig)));
if (!$success) {
logNewMessage(LOG_ERR, '[' . $ldapUser .'] Unable to delete user ' . $this->getAccountContainer()->finalDN . ' from group: ' . $toRem[$i] . ' (' . ldap_err2str(ldap_errno($_SESSION['ldap']->server())) . ').');
$messages[] = array('ERROR', sprintf(_('Was unable to remove attributes from DN: %s.'), $toRem[$i]), ldap_error($_SESSION['ldap']->server()));
}
else {
logNewMessage(LOG_NOTICE, '[' . $ldapUser .'] Removed user ' . $this->getAccountContainer()->finalDN . ' from group: ' . $toRem[$i]);
}
}
}
return $messages;
}
2013-04-06 15:00:53 +00:00
/**
* In this function the LDAP account is built up.
*
* @param array $rawAccounts list of hash arrays (name => value) from user input
* @param array $ids list of IDs for column position (e.g. "posixAccount_uid" => 5)
* @param array $partialAccounts list of hash arrays (name => value) which are later added to LDAP
* @param array $selectedModules list of selected account modules
* @return array list of error messages if any
*/
public function build_uploadAccounts($rawAccounts, $ids, &$partialAccounts, $selectedModules) {
$errors = array();
for ($i = 0; $i < sizeof($rawAccounts); $i++) {
// add object class
2013-04-07 17:28:09 +00:00
if (!in_array('user', $partialAccounts[$i]['objectClass'])) $partialAccounts[$i]['objectClass'][] = 'user';
2013-04-06 15:00:53 +00:00
// cn + sAMAccountName
2013-04-07 17:28:09 +00:00
if ($rawAccounts[$i][$ids['windowsUser_name']] != "") {
if (get_preg($rawAccounts[$i][$ids['windowsUser_name']], 'username')) {
$partialAccounts[$i]['cn'] = $rawAccounts[$i][$ids['windowsUser_name']];
$partialAccounts[$i]['sAMAccountName'] = $rawAccounts[$i][$ids['windowsUser_name']] . '$';
2013-04-06 15:00:53 +00:00
}
else {
$errMsg = $this->messages['cn'][1];
array_push($errMsg, array($i));
$errors[] = $errMsg;
}
}
// description
2013-04-07 17:28:09 +00:00
if ($rawAccounts[$i][$ids['windowsUser_description']] != "") {
$partialAccounts[$i]['description'] = $rawAccounts[$i][$ids['windowsUser_description']];
2013-04-06 15:00:53 +00:00
}
// location
2013-04-07 17:28:09 +00:00
if ($rawAccounts[$i][$ids['windowsUser_l']] != "") {
$partialAccounts[$i]['l'] = $rawAccounts[$i][$ids['windowsUser_l']];
2013-04-06 15:00:53 +00:00
}
2013-04-07 17:28:09 +00:00
// user account
$partialAccounts[$i]['userAccountControl'][0] = windowsUser::DEFAULT_ACCOUNT_CONTROL;
2013-04-06 15:00:53 +00:00
}
return $errors;
}
/**
* Returns a list of PDF entries
*/
public function get_pdfEntries() {
$return = array();
$this->addSimplePDFField($return, 'cn', _('User name'));
$this->addSimplePDFField($return, 'description', _('Description'));
$this->addSimplePDFField($return, 'displayName', _('Display name'));
$this->addSimplePDFField($return, 'givenName', _('First name'));
$this->addSimplePDFField($return, 'initials', _('Initials'));
$this->addSimplePDFField($return, 'l', _('Location'));
$this->addSimplePDFField($return, 'mail', _('Email address'));
$this->addSimplePDFField($return, 'otherTelephone', _('Other telephone numbers'));
$this->addSimplePDFField($return, 'physicalDeliveryOfficeName', _('Office name'));
$this->addSimplePDFField($return, 'postalCode', _('Postal code'));
$this->addSimplePDFField($return, 'postOfficeBox', _('Post office box'));
$this->addSimplePDFField($return, 'sn', _('Last name'));
$this->addSimplePDFField($return, 'st', _('State'));
$this->addSimplePDFField($return, 'streetAddress', _('Street'));
$this->addSimplePDFField($return, 'telephoneNumber', _('Telephone number'));
$this->addSimplePDFField($return, 'url', _('Other web sites'));
$this->addSimplePDFField($return, 'wWWHomePage', _('Web site'));
return $return;
}
2013-04-07 17:28:09 +00:00
/**
* This method specifies if a module manages password attributes. The module alias will
* then appear as option in the GUI.
* <br>If the module only wants to get notified about password changes then return false.
*
* @return boolean true if this module manages password attributes
*/
public function managesPasswordAttributes() {
return true;
}
/**
* Specifies if this module supports to force that a user must change his password on next login.
*
* @return boolean force password change supported
*/
public function supportsForcePasswordChange() {
return true;
2013-04-07 17:28:09 +00:00
}
/**
* This function is called whenever the password should be changed. Account modules
* must change their password attributes only if the modules list contains their module name.
*
* @param String $password new password
* @param array $modules list of modules for which the password should be changed
* @param boolean $forcePasswordChange force the user to change his password at next login
* @return array list of error messages if any as parameter array for StatusMessage
* e.g. return arrray(array('ERROR', 'Password change failed.'))
*/
public function passwordChangeRequested($password, $modules, $forcePasswordChange) {
if (!in_array(get_class($this), $modules)) {
return array();
}
$pwdBin = iconv('UTF-8', 'UTF-16LE', '"' . $password . '"');
$this->orig['unicodePwd'][0] = 'unknown';
$this->attributes['unicodePwd'][0] = $pwdBin;
$this->attributes['pwdLastSet'][0] = '-1';
2013-04-07 17:28:09 +00:00
return array();
}
2013-04-06 15:00:53 +00:00
/**
* Returns if the account is currently deactivated.
*
* @param array $attrs LDAP attributes
* @return boolean is deactivated
*/
public static function isDeactivated($attrs) {
$myAttrs = array_change_key_case($attrs, CASE_LOWER);
if (!isset($myAttrs['useraccountcontrol'][0])) {
return false;
}
return intval($myAttrs['useraccountcontrol'][0]) & windowsUser::AC_ACCOUNT_DISABLED;
}
2013-04-06 15:00:53 +00:00
/**
* Sets if the account is currently deactivated.
*
* @param array $attrs LDAP attributes to modify
* @param boolean $deactivated is deactivated
*/
public static function setIsDeactivated(&$attrs, $deactivated) {
foreach ($attrs as $key => $value) {
if (strtolower($key) == 'useraccountcontrol') {
if ($deactivated) {
$attrs[$key][0] = intval($attrs[$key][0]) | windowsUser::AC_ACCOUNT_DISABLED;
}
else {
if (intval($attrs[$key][0]) & windowsUser::AC_ACCOUNT_DISABLED) {
$attrs[$key][0] = intval($attrs[$key][0]) - windowsUser::AC_ACCOUNT_DISABLED;
}
}
}
}
}
2013-04-06 15:00:53 +00:00
/**
* Returns if the account is currently locked out.
*
* @param array $attrs LDAP attributes
* @return boolean is locked out
*/
private static function isLockedOut($attrs) {
$myAttrs = array_change_key_case($attrs, CASE_LOWER);
if (!isset($attrs['useraccountcontrol'][0])) {
return false;
}
return intval($attrs['useraccountcontrol'][0]) & windowsUser::AC_LOCKED_OUT;
}
/**
* Unlocks the account.
*
* @param array $attrs LDAP attributes to modify
*/
public static function unlock(&$attrs) {
foreach ($attrs as $key => $value) {
if (strtolower($key) == 'useraccountcontrol') {
if (intval($attrs[$key][0]) & windowsUser::AC_LOCKED_OUT) {
$attrs[$key][0] = intval($attrs[$key][0]) - windowsUser::AC_LOCKED_OUT;
}
}
}
}
/**
* Returns if the account requires a smartcard to login.
*
* @param array $attrs LDAP attributes
* @return boolean requires a smartcard
*/
public static function isSmartCardRequired($attrs) {
$myAttrs = array_change_key_case($attrs, CASE_LOWER);
if (!isset($myAttrs['useraccountcontrol'][0])) {
return false;
}
return intval($myAttrs['useraccountcontrol'][0]) & windowsUser::AC_SMARTCARD_REQUIRED;
}
/**
* Sets if the account requires a smartcard to login.
*
* @param array $attrs LDAP attributes to modify
* @param boolean $requireCard requires a smartcard
*/
public static function setIsSmartCardRequired(&$attrs, $requireCard) {
foreach ($attrs as $key => $value) {
if (strtolower($key) == 'useraccountcontrol') {
if ($requireCard) {
$attrs[$key][0] = intval($attrs[$key][0]) | windowsUser::AC_SMARTCARD_REQUIRED;
}
else {
if (intval($attrs[$key][0]) & windowsUser::AC_SMARTCARD_REQUIRED) {
$attrs[$key][0] = intval($attrs[$key][0]) - windowsUser::AC_SMARTCARD_REQUIRED;
}
}
}
}
}
/**
* Returns if the account never expires.
*
* @param array $attrs LDAP attributes
* @return boolean never expires
*/
public static function isNeverExpiring($attrs) {
$myAttrs = array_change_key_case($attrs, CASE_LOWER);
if (!isset($myAttrs['useraccountcontrol'][0])) {
return false;
}
return intval($myAttrs['useraccountcontrol'][0]) & windowsUser::AC_PWD_NEVER_EXPIRES;
}
/**
* Sets if the account never expires.
*
* @param array $attrs LDAP attributes to modify
* @param boolean $neverExpires never expires
*/
public static function setIsNeverExpiring(&$attrs, $neverExpires) {
foreach ($attrs as $key => $value) {
if (strtolower($key) == 'useraccountcontrol') {
if ($neverExpires) {
$attrs[$key][0] = intval($attrs[$key][0]) | windowsUser::AC_PWD_NEVER_EXPIRES;
}
else {
if (intval($attrs[$key][0]) & windowsUser::AC_PWD_NEVER_EXPIRES) {
$attrs[$key][0] = intval($attrs[$key][0]) - windowsUser::AC_PWD_NEVER_EXPIRES;
}
}
}
}
}
/**
* Finds all existing groups.
*
* @return array group DNs
*/
private function findGroups() {
if ($this->groupCache != null) {
return $this->groupCache;
}
$return = array();
$types = array('group');
$results = searchLDAPByFilter('(objectClass=group)', array('dn'), $types);
$count = sizeof($results);
for ($i = 0; $i < $count; $i++) {
if (isset($results[$i]['dn'])) {
$return[] = $results[$i]['dn'];
}
}
$this->groupCache = $return;
return $return;
}
}
2013-04-06 15:00:53 +00:00
?>