getSelfServiceSearchAttributes(); $return = array_merge($return, $attributes); } $return = array_unique($return); return array_values($return); } /** * Returns the field settings for the self service. * * @param string $scope account type * @return array settings */ function getSelfServiceFieldSettings($scope) { $return = array(); $modules = getAvailableModules($scope); for ($i = 0; $i < sizeof($modules); $i++) { $m = moduleCache::getModule($modules[$i], $scope); $settings = $m->getSelfServiceFields(); if (sizeof($settings) > 0) { $return[$modules[$i]] = $settings; } } return $return; } /** * Returns meta HTML code for each self service field. * * @param string $scope account type * @param array $fields input fields (array( => array(, , ...))) * @param array $attributes LDAP attributes (attribute names in lower case) * @param boolean $passwordChangeOnly indicates that the user is only allowed to change his password and no LDAP content is readable * @param array $readOnlyFields list of read-only fields * @return array meta HTML code (array( => htmlResponsiveRow)) */ function getSelfServiceOptions($scope, $fields, $attributes, $passwordChangeOnly, $readOnlyFields) { $return = array(); $modules = getAvailableModules($scope); for ($i = 0; $i < sizeof($modules); $i++) { if (!isset($fields[$modules[$i]])) { continue; } $m = moduleCache::getModule($modules[$i], $scope); $modReadOnlyFields = array(); for ($r = 0; $r < sizeof($readOnlyFields); $r++) { $parts = explode('_', $readOnlyFields[$r]); if ($parts[0] == $modules[$i]) { $modReadOnlyFields[] = $parts[1]; } } $code = $m->getSelfServiceOptions($fields[$modules[$i]], $attributes, $passwordChangeOnly, $modReadOnlyFields); if (sizeof($code) > 0) { $return[$modules[$i]] = $code; } } return $return; } /** * Checks if all input values are correct and returns the LDAP commands which should be executed. * * @param string $scope account type * @param string $fields input fields (array( => array(, , ...))) * @param array $attributes LDAP attributes * @param boolean $passwordChangeOnly indicates that the user is only allowed to change his password and no LDAP content is readable * @param array $readOnlyFields list of read-only fields * @return array messages and LDAP commands (array('messages' => array(), 'add' => array(), 'del' => array(), 'mod' => array())) */ function checkSelfServiceOptions($scope, $fields, $attributes, $passwordChangeOnly, $readOnlyFields) { $return = array('messages' => array(), 'add' => array(), 'del' => array(), 'mod' => array(), 'info' => array()); $modules = getAvailableModules($scope); for ($i = 0; $i < sizeof($modules); $i++) { if (!isset($fields[$modules[$i]])) { continue; } $m = moduleCache::getModule($modules[$i], $scope); $modReadOnlyFields = array(); for ($r = 0; $r < sizeof($readOnlyFields); $r++) { $parts = explode('_', $readOnlyFields[$r]); if ($parts[0] == $modules[$i]) { $modReadOnlyFields[] = $parts[1]; } } $result = $m->checkSelfServiceOptions($fields[$modules[$i]], $attributes, $passwordChangeOnly, $modReadOnlyFields); if (sizeof($result['messages']) > 0) { $return['messages'] = array_merge($result['messages'], $return['messages']); } if (sizeof($result['add']) > 0) { $return['add'] = array_merge($result['add'], $return['add']); } if (sizeof($result['del']) > 0) { $return['del'] = array_merge($result['del'], $return['del']); } if (sizeof($result['mod']) > 0) { $return['mod'] = array_merge($result['mod'], $return['mod']); } if (sizeof($result['info']) > 0) { $return['info'] = array_merge($result['info'], $return['info']); } } return $return; } /** * Returns a list of all available self service profiles (without .conf) * * @return array profile names (array( => array(, , ...))) */ function getSelfServiceProfiles() { $types = LAM\TYPES\getTypes(); $dir = dir(substr(__FILE__, 0, strlen(__FILE__) - 20) . "/config/selfService"); $ret = array(); if ($dir === false) { logNewMessage(LOG_ERR, 'Unable to read self service profiles'); return $ret; } while ($entry = $dir->read()){ $ext = substr($entry, strrpos($entry, '.') + 1); $name = substr($entry, 0, strrpos($entry, '.')); // check if extension is right, add to profile list if (in_array($ext, $types)) { $ret[$ext][] = $name; } } ksort($ret); foreach ($ret as $key => $value) { sort($ret[$key]); } return $ret; } /** * Loads all settings of a self service profile. * * @param string $name profile name * @param string $scope account type * @return selfServiceProfile true if file was readable */ function loadSelfServiceProfile($name, $scope) { if (!preg_match("/^[0-9a-z _-]+$/i", $name) || !preg_match("/^[0-9a-z _-]+$/i", $scope)) { return false; } $profile = new selfServiceProfile(); $file = substr(__FILE__, 0, strlen(__FILE__) - 20) . "/config/selfService/" . $name . "." . $scope; if (is_file($file) === True) { $file = @fopen($file, "r"); if ($file) { $data = fread($file, 10000000); $profile = unserialize($data); fclose($file); } else { StatusMessage("ERROR", "", _("Unable to load profile!") . " " . $file); } } else { StatusMessage("ERROR", "", _("Unable to load profile!") . " " . $file); } return $profile; } /** * Saves a self service profile. * * File is created, if needed * * @param string $name name of the account profile * @param string $scope account type * @param selfServiceProfile $profile self service profile * @return boolean true, if saving succeeded */ function saveSelfServiceProfile($name, $scope, $profile) { // check profile name if (!preg_match("/^[0-9a-z _-]+$/i", $scope) || !preg_match("/^[0-9a-z _-]+$/i", $name)) { return false; } if (!get_class($profile) === 'selfServiceProfile') { return false; } $path = substr(__FILE__, 0, strlen(__FILE__) - 20) . "/config/selfService/" . $name . "." . $scope; $file = @fopen($path, "w"); if ($file) { // write settings to file fputs($file, serialize($profile)); // close file fclose($file); } else { return false; } return true; } /** * Checks if a service profile is writable. * * @param string $name profile name * @param string $scope account type * @return boolean true if file is writable */ function isSelfServiceProfileWritable($name, $scope) { // check profile name if (!preg_match("/^[0-9a-z _-]+$/i", $scope) || !preg_match("/^[0-9a-z _-]+$/i", $name)) { return false; } $path = substr(__FILE__, 0, strlen(__FILE__) - 20) . "/config/selfService/" . $name . "." . $scope; return is_writable($path); } /** * Returns a hash array (module name => elements) of all module options for the configuration page. * * @param string $scope account type * @param selfServiceProfile $profile currently edited profile * @return array configuration options */ function getSelfServiceSettings($scope, $profile) { $return = array(); $modules = getAvailableModules($scope); for ($i = 0; $i < sizeof($modules); $i++) { $m = moduleCache::getModule($modules[$i], $scope); $return[$modules[$i]] = $m->getSelfServiceSettings($profile); } return $return; } /** * Checks if the self service settings are valid * * @param string $scope account type * @param array $options hash array containing all options (name => array(...)) * @param selfServiceProfile $profile profile * @return array list of error messages */ function checkSelfServiceSettings($scope, &$options, &$profile) { $return = array(); $modules = getAvailableModules($scope); for ($i = 0; $i < sizeof($modules); $i++) { $m = moduleCache::getModule($modules[$i], $scope); $errors = $m->checkSelfServiceSettings($options, $profile); $return = array_merge($return, $errors); } return $return; } /** * Returns if script runs inside self service. * * @return boolean is self service */ function isSelfService() { return session_name() == 'SELFSERVICE'; } /** * Opens the LDAP connection and returns the handle. No bind is done. * * @param selfServiceProfile $profile profile * @return handle LDAP handle or null if connection failed */ function openSelfServiceLdapConnection($profile) { $server = connectToLDAP($profile->serverURL, $profile->useTLS); if ($server != null) { // follow referrals ldap_set_option($server, LDAP_OPT_REFERRALS, $profile->followReferrals); } return $server; } /** * Binds the LDAP connections with given user and password. * * @param handle $handle LDAP handle * @param selfServiceProfile profile * @param string $userDn bind DN * @param string $password bind password * @return boolean binding successful */ function bindLdapUser($handle, $profile, $userDn, $password) { if ($profile->useForAllOperations) { $userDn = $profile->LDAPUser; $password = deobfuscateText($profile->LDAPPassword); } return @ldap_bind($handle, $userDn, $password); } /** * Includes all settings of a self service profile. * * @package selfService */ class selfServiceProfile { /** server address */ public $serverURL; /** use TLS */ public $useTLS; /** LDAP suffix */ public $LDAPSuffix; /** LDAP user DN*/ public $LDAPUser; /** LDAP password */ public $LDAPPassword; /** use bind user also for read/modify operations */ public $useForAllOperations; /** LDAP search attribute */ public $searchAttribute; /** HTTP authentication */ public $httpAuthentication; /** header for self service pages */ public $pageHeader; /** base color */ public $baseColor = '#fffde2'; /** list of additional CSS links (separated by \n) */ public $additionalCSS; /** describing text for user login */ public $loginCaption; /** label for password input */ public $passwordLabel; /** describing text for search attribute */ public $loginAttributeText; /** additional LDAP filter for accounts */ public $additionalLDAPFilter; /** describing text for self service main page */ public $mainPageText; /** input fields * Format: array( *
array(array('name' => , 'fields' => array(, ))), *
array(array('name' => , 'fields' => array(, ))) *
) * */ public $inputFields; /** * List of fields that are set in read-only mode. */ public $readOnlyFields; /** List of override values for field labels: array( => label) */ public $relabelFields; /** configuration settings of modules */ public $moduleSettings; /** language for self service */ public $language = 'en_GB.utf8'; /** disallow user to change language */ public $enforceLanguage = false; public $followReferrals = 0; public $timeZone = 'Europe/London'; public $twoFactorAuthentication = TwoFactorProviderService::TWO_FACTOR_NONE; public $twoFactorAuthenticationURL = 'https://localhost'; public $twoFactorAuthenticationInsecure = false; public $twoFactorAuthenticationLabel = null; public $twoFactorAuthenticationOptional = false; public $twoFactorAuthenticationCaption = ''; public $twoFactorAuthenticationClientId = ''; public $twoFactorAuthenticationSecretKey = ''; /** provider for captcha (-/google) */ public $captchaProvider = '-'; /** Google reCAPTCHA site key */ public $reCaptchaSiteKey = ''; /** Google reCAPTCHA secret key */ public $reCaptchaSecretKey = ''; /** enable captcha on self service login */ public $captchaOnLogin = false; /** base URL for the website (e.g. https://example.com) for link generation */ private $baseUrl = ''; /** * Constructor * * @return selfServiceProfile */ function __construct() { // set default values $this->serverURL = "localhost"; $this->useTLS = false; $this->LDAPSuffix = "dc=my-domain,dc=com"; $this->LDAPUser = ""; $this->LDAPPassword = ""; $this->useForAllOperations = false; $this->searchAttribute = "uid"; $this->additionalLDAPFilter = ''; $this->httpAuthentication = false; $this->pageHeader = '

'; $this->additionalCSS = ''; $this->baseColor = '#fffde2'; $this->loginCaption = '' . _("Welcome to LAM self service. Please enter your user name and password.") . ''; $this->loginAttributeText = _('User name'); $this->passwordLabel = ''; $this->mainPageText = "

LAM self service

\n" . _("Here you can change your personal settings."); $this->inputFields = array( array('name' => _('Personal data'), 'fields' => array('inetOrgPerson_firstName', 'inetOrgPerson_lastName', 'inetOrgPerson_mail', 'inetOrgPerson_telephoneNumber', 'inetOrgPerson_mobile', 'inetOrgPerson_faxNumber', 'inetOrgPerson_street', 'inetOrgPerson_postalAddress')), array('name' => _('Password'), 'fields' => array('posixAccount_password')) ); $this->readOnlyFields = array(); $this->relabelFields = array(); $this->moduleSettings = array(); $this->language = 'en_GB.utf8'; $this->enforceLanguage = true; $this->followReferrals = 0; $this->timeZone = 'Europe/London'; $this->twoFactorAuthentication = TwoFactorProviderService::TWO_FACTOR_NONE; $this->twoFactorAuthenticationURL = 'https://localhost'; $this->twoFactorAuthenticationInsecure = false; $this->twoFactorAuthenticationLabel = null; $this->twoFactorAuthenticationOptional = false; $this->twoFactorAuthenticationCaption = ''; $this->twoFactorAuthenticationClientId = ''; $this->twoFactorAuthenticationSecretKey = ''; $this->captchaProvider = '-'; $this->reCaptchaSiteKey = ''; $this->reCaptchaSecretKey = ''; $this->captchaOnLogin = false; $this->baseUrl = ''; } /** * Returns the server's base URL (e.g. https://www.example.com). * * @return string URL */ public function getBaseUrl() { if (!empty($this->baseUrl)) { return $this->baseUrl; } $callingUrl = getCallingURL(); $matches = array(); if (preg_match('/^(http(s)?:\\/\\/[^\\/]+)\\/.+$/', $callingUrl, $matches)) { return $matches[1]; } } /** * Sets the server's base URL (e.g. https://www.example.com). * * @param string $url URL */ public function setBaseUrl($url) { $this->baseUrl = $url; if (!empty($url) && (substr($url, -1, 1) === '/')) { $this->baseUrl = substr($url, 0, -1); } } } ?>