LDAPAccountManager/lam/lib/selfService.inc

554 lines
16 KiB
PHP
Raw Normal View History

2017-02-11 17:16:08 +00:00
<?php
use \LAM\LIB\TWO_FACTOR\TwoFactorProviderService;
2006-06-28 15:13:16 +00:00
/*
2009-10-27 18:47:12 +00:00
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
2020-01-08 19:38:26 +00:00
Copyright (C) 2006 - 2020 Roland Gruber
2006-06-28 15:13:16 +00:00
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
*/
/**
* Interface between modules and self service pages.
2006-07-10 19:30:14 +00:00
* This file also includes the self service profile class and helper functions.
2006-09-09 11:43:19 +00:00
*
2006-06-28 15:13:16 +00:00
* @package selfService
* @author Roland Gruber
*/
/** modules */
2017-02-11 17:16:08 +00:00
include_once "modules.inc";
2006-07-10 19:30:14 +00:00
/** account types */
2017-02-11 17:16:08 +00:00
include_once "types.inc";
/** 2-factor */
include_once '2factor.inc';
2006-06-28 15:13:16 +00:00
/**
* Returns if this is a LAM Pro installation.
*
* @return boolean LAM Pro installation
*/
function isLAMProVersion() {
$dir = substr(__FILE__, 0, strlen(__FILE__) - 20) . "/templates/selfService";
return is_dir($dir);
}
2006-06-28 15:13:16 +00:00
/**
* Returns a list of possible search attributes for the self service.
*
* @param string $scope account type
* @return array attributes
*/
function getSelfServiceSearchAttributes($scope) {
$return = array();
$modules = getAvailableModules($scope);
for ($i = 0; $i < sizeof($modules); $i++) {
2013-05-09 19:10:35 +00:00
$m = moduleCache::getModule($modules[$i], $scope);
2006-06-28 15:13:16 +00:00
$attributes = $m->getSelfServiceSearchAttributes();
$return = array_merge($return, $attributes);
}
2006-08-07 16:26:19 +00:00
$return = array_unique($return);
2019-03-09 08:19:39 +00:00
return array_values($return);
2006-06-28 15:13:16 +00:00
}
2006-07-10 19:30:14 +00:00
2006-07-16 17:15:37 +00:00
/**
* 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++) {
2013-05-09 19:10:35 +00:00
$m = moduleCache::getModule($modules[$i], $scope);
2006-07-16 17:15:37 +00:00
$settings = $m->getSelfServiceFields();
2019-03-09 08:19:39 +00:00
if (sizeof($settings) > 0) {
$return[$modules[$i]] = $settings;
}
2006-07-16 17:15:37 +00:00
}
return $return;
}
2006-07-23 15:04:12 +00:00
/**
* Returns meta HTML code for each self service field.
*
* @param string $scope account type
* @param array $fields input fields (array(<moduleName> => array(<field1>, <field2>, ...)))
* @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
2012-08-18 15:55:43 +00:00
* @param array $readOnlyFields list of read-only fields
2015-08-04 18:41:12 +00:00
* @return array meta HTML code (array(<moduleName> => htmlResponsiveRow))
2006-07-23 15:04:12 +00:00
*/
2012-08-18 15:55:43 +00:00
function getSelfServiceOptions($scope, $fields, $attributes, $passwordChangeOnly, $readOnlyFields) {
2006-07-23 15:04:12 +00:00
$return = array();
$modules = getAvailableModules($scope);
for ($i = 0; $i < sizeof($modules); $i++) {
2019-03-09 08:19:39 +00:00
if (!isset($fields[$modules[$i]])) {
continue;
}
2013-05-09 19:10:35 +00:00
$m = moduleCache::getModule($modules[$i], $scope);
2012-08-18 15:55:43 +00:00
$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);
2019-03-09 08:19:39 +00:00
if (sizeof($code) > 0) {
$return[$modules[$i]] = $code;
}
2006-07-23 15:04:12 +00:00
}
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(<moduleName> => array(<field1>, <field2>, ...)))
* @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
2012-08-18 15:55:43 +00:00
* @param array $readOnlyFields list of read-only fields
2006-07-23 15:04:12 +00:00
* @return array messages and LDAP commands (array('messages' => array(), 'add' => array(), 'del' => array(), 'mod' => array()))
*/
2012-08-18 15:55:43 +00:00
function checkSelfServiceOptions($scope, $fields, $attributes, $passwordChangeOnly, $readOnlyFields) {
2011-02-26 13:14:10 +00:00
$return = array('messages' => array(), 'add' => array(), 'del' => array(), 'mod' => array(), 'info' => array());
2006-07-23 15:04:12 +00:00
$modules = getAvailableModules($scope);
for ($i = 0; $i < sizeof($modules); $i++) {
2019-03-09 08:19:39 +00:00
if (!isset($fields[$modules[$i]])) {
continue;
}
2013-05-09 19:10:35 +00:00
$m = moduleCache::getModule($modules[$i], $scope);
2012-08-18 15:55:43 +00:00
$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);
2019-03-09 08:19:39 +00:00
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']);
}
2006-07-23 15:04:12 +00:00
}
return $return;
}
2006-07-10 19:30:14 +00:00
/**
* Returns a list of all available self service profiles (without .conf)
*
* @return array profile names (array(<account type> => array(<profile1>, <profile2>, ...)))
*/
function getSelfServiceProfiles() {
2016-12-19 20:32:08 +00:00
$types = LAM\TYPES\getTypes();
2006-07-10 19:30:14 +00:00
$dir = dir(substr(__FILE__, 0, strlen(__FILE__) - 20) . "/config/selfService");
$ret = array();
2017-11-04 14:09:29 +00:00
if ($dir === false) {
logNewMessage(LOG_ERR, 'Unable to read self service profiles');
return $ret;
}
2006-07-10 19:30:14 +00:00
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);
2011-12-10 09:29:38 +00:00
foreach ($ret as $key => $value) {
sort($ret[$key]);
}
2006-07-10 19:30:14 +00:00
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) {
2019-03-09 08:19:39 +00:00
if (!preg_match("/^[0-9a-z _-]+$/i", $name) || !preg_match("/^[0-9a-z _-]+$/i", $scope)) {
return false;
}
2006-07-10 19:30:14 +00:00
$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) {
2013-06-14 18:28:25 +00:00
$data = fread($file, 10000000);
2006-07-10 19:30:14 +00:00
$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
2019-03-09 08:19:39 +00:00
if (!preg_match("/^[0-9a-z _-]+$/i", $scope) || !preg_match("/^[0-9a-z _-]+$/i", $name)) {
return false;
}
2006-07-10 19:30:14 +00:00
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;
}
2011-12-10 08:46:16 +00:00
/**
* 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
2019-03-09 08:19:39 +00:00
if (!preg_match("/^[0-9a-z _-]+$/i", $scope) || !preg_match("/^[0-9a-z _-]+$/i", $name)) {
return false;
}
2011-12-10 08:46:16 +00:00
$path = substr(__FILE__, 0, strlen(__FILE__) - 20) . "/config/selfService/" . $name . "." . $scope;
return is_writable($path);
}
2006-11-21 17:37:12 +00:00
/**
* 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
2006-11-21 17:37:12 +00:00
* @return array configuration options
*/
function getSelfServiceSettings($scope, $profile) {
2006-11-21 17:37:12 +00:00
$return = array();
$modules = getAvailableModules($scope);
for ($i = 0; $i < sizeof($modules); $i++) {
2013-05-09 19:10:35 +00:00
$m = moduleCache::getModule($modules[$i], $scope);
$return[$modules[$i]] = $m->getSelfServiceSettings($profile);
2006-11-21 17:37:12 +00:00
}
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
2006-11-21 17:37:12 +00:00
* @return array list of error messages
*/
function checkSelfServiceSettings($scope, &$options, &$profile) {
2006-11-21 17:37:12 +00:00
$return = array();
$modules = getAvailableModules($scope);
for ($i = 0; $i < sizeof($modules); $i++) {
2013-05-09 19:10:35 +00:00
$m = moduleCache::getModule($modules[$i], $scope);
$errors = $m->checkSelfServiceSettings($options, $profile);
2006-11-21 17:37:12 +00:00
$return = array_merge($return, $errors);
}
return $return;
}
2015-05-14 09:18:45 +00:00
/**
* Returns if script runs inside self service.
2015-08-04 18:41:12 +00:00
*
2015-05-14 09:18:45 +00:00
* @return boolean is self service
*/
function isSelfService() {
return session_name() == 'SELFSERVICE';
}
2019-01-01 09:54:31 +00:00
/**
* 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);
}
2006-07-10 19:30:14 +00:00
/**
* Includes all settings of a self service profile.
*
* @package selfService
*/
class selfServiceProfile {
2006-09-09 11:43:19 +00:00
2006-07-10 19:30:14 +00:00
/** server address */
2007-10-15 17:20:51 +00:00
public $serverURL;
2015-08-04 18:41:12 +00:00
2011-08-20 16:27:07 +00:00
/** use TLS */
public $useTLS;
2006-09-09 11:43:19 +00:00
2006-07-10 19:30:14 +00:00
/** LDAP suffix */
2007-10-15 17:20:51 +00:00
public $LDAPSuffix;
2006-09-09 11:43:19 +00:00
2006-07-14 17:44:11 +00:00
/** LDAP user DN*/
2007-10-15 17:20:51 +00:00
public $LDAPUser;
2006-09-09 11:43:19 +00:00
2006-07-14 17:44:11 +00:00
/** LDAP password */
2007-10-15 17:20:51 +00:00
public $LDAPPassword;
2015-08-04 18:41:12 +00:00
2013-11-01 15:54:49 +00:00
/** use bind user also for read/modify operations */
public $useForAllOperations;
2006-09-09 11:43:19 +00:00
2006-07-10 19:30:14 +00:00
/** LDAP search attribute */
2007-10-15 17:20:51 +00:00
public $searchAttribute;
2015-08-04 18:41:12 +00:00
2011-08-24 20:03:43 +00:00
/** HTTP authentication */
public $httpAuthentication;
2015-08-04 18:41:12 +00:00
2009-02-13 18:52:59 +00:00
/** header for self service pages */
public $pageHeader;
2015-08-04 18:41:12 +00:00
2018-10-22 19:11:31 +00:00
/** base color */
public $baseColor = '#fffde2';
2009-02-14 13:50:20 +00:00
/** list of additional CSS links (separated by \n) */
public $additionalCSS;
2006-09-09 11:43:19 +00:00
2006-07-10 19:30:14 +00:00
/** describing text for user login */
2007-10-15 17:20:51 +00:00
public $loginCaption;
2015-08-04 18:41:12 +00:00
2019-08-08 19:10:32 +00:00
/** describing text for user login */
public $loginFooter;
/** label for password input */
public $passwordLabel;
2006-09-09 11:43:19 +00:00
2006-07-10 19:30:14 +00:00
/** describing text for search attribute */
2007-10-15 17:20:51 +00:00
public $loginAttributeText;
2006-09-09 11:43:19 +00:00
/** additional LDAP filter for accounts */
public $additionalLDAPFilter;
2015-08-04 18:41:12 +00:00
2006-07-16 17:15:37 +00:00
/** describing text for self service main page */
2007-10-15 17:20:51 +00:00
public $mainPageText;
2006-09-09 11:43:19 +00:00
2019-08-08 19:10:32 +00:00
/** describing text for self service main page */
public $mainPageFooter;
2006-07-16 17:15:37 +00:00
/** input fields
* Format: array(
* <br> array(array('name' => <group name 1>, 'fields' => array(<field1>, <field2>))),
* <br> array(array('name' => <group name 2>, 'fields' => array(<field3>, <field4>)))
* <br> )
2006-09-09 11:43:19 +00:00
*
2006-07-16 17:15:37 +00:00
*/
2007-10-15 17:20:51 +00:00
public $inputFields;
2015-08-04 18:41:12 +00:00
2012-08-18 15:55:43 +00:00
/**
* List of fields that are set in read-only mode.
*/
public $readOnlyFields;
2015-08-04 18:41:12 +00:00
2013-11-30 15:02:06 +00:00
/** List of override values for field labels: array(<field ID> => label) */
public $relabelFields;
2015-08-04 18:41:12 +00:00
2006-11-21 17:37:12 +00:00
/** configuration settings of modules */
2007-10-15 17:20:51 +00:00
public $moduleSettings;
2015-08-04 18:41:12 +00:00
2014-02-02 16:32:39 +00:00
/** language for self service */
public $language = 'en_GB.utf8';
/** disallow user to change language */
public $enforceLanguage = false;
2015-08-04 18:41:12 +00:00
2014-10-26 09:33:43 +00:00
public $followReferrals = 0;
2006-09-09 11:43:19 +00:00
2015-11-07 09:14:48 +00:00
public $timeZone = 'Europe/London';
2017-02-11 17:16:08 +00:00
public $twoFactorAuthentication = TwoFactorProviderService::TWO_FACTOR_NONE;
2017-01-23 18:57:50 +00:00
public $twoFactorAuthenticationURL = 'https://localhost';
public $twoFactorAuthenticationInsecure = false;
2017-01-30 19:02:31 +00:00
public $twoFactorAuthenticationLabel = null;
2017-01-31 19:50:51 +00:00
public $twoFactorAuthenticationOptional = false;
public $twoFactorAuthenticationCaption = '';
2019-01-01 09:54:31 +00:00
public $twoFactorAuthenticationClientId = '';
public $twoFactorAuthenticationSecretKey = '';
2019-08-11 07:39:47 +00:00
public $twoFactorAuthenticationAttribute = 'uid';
2020-01-08 19:38:26 +00:00
public $twoFactorAuthenticationDomain = '';
2017-01-23 18:57:50 +00:00
2018-02-10 16:31:03 +00:00
/** 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;
2019-03-09 08:41:32 +00:00
/** base URL for the website (e.g. https://example.com) for link generation */
private $baseUrl = '';
2006-07-10 19:30:14 +00:00
/**
* Constructor
*
* @return selfServiceProfile
*/
2007-12-28 16:08:56 +00:00
function __construct() {
2006-07-10 19:30:14 +00:00
// set default values
$this->serverURL = "localhost";
2011-08-20 16:27:07 +00:00
$this->useTLS = false;
2006-08-03 18:02:21 +00:00
$this->LDAPSuffix = "dc=my-domain,dc=com";
2006-07-14 17:44:11 +00:00
$this->LDAPUser = "";
$this->LDAPPassword = "";
2013-11-01 15:54:49 +00:00
$this->useForAllOperations = false;
2006-07-10 19:30:14 +00:00
$this->searchAttribute = "uid";
$this->additionalLDAPFilter = '';
2011-08-24 20:03:43 +00:00
$this->httpAuthentication = false;
2014-03-29 11:04:14 +00:00
$this->pageHeader = '<table border=0 width="100%" class="lamHeader ui-corner-all"><tr><td align="left" height="30"><a class="lamLogo" href="http://www.ldap-account-manager.org/" target="new_window">LDAP Account Manager</a></td></tr></table><br>';
2009-02-14 13:50:20 +00:00
$this->additionalCSS = '';
2018-10-22 19:11:31 +00:00
$this->baseColor = '#fffde2';
2013-01-12 11:27:02 +00:00
$this->loginCaption = '<b>' . _("Welcome to LAM self service. Please enter your user name and password.") . '</b>';
2012-05-25 18:22:43 +00:00
$this->loginAttributeText = _('User name');
$this->passwordLabel = '';
2012-05-25 18:22:43 +00:00
$this->mainPageText = "<h1>LAM self service</h1>\n" . _("Here you can change your personal settings.");
2006-08-03 18:02:21 +00:00
$this->inputFields = array(
2012-05-25 18:22:43 +00:00
array('name' => _('Personal data'),
2006-08-03 18:02:21 +00:00
'fields' => array('inetOrgPerson_firstName', 'inetOrgPerson_lastName', 'inetOrgPerson_mail',
'inetOrgPerson_telephoneNumber', 'inetOrgPerson_mobile', 'inetOrgPerson_faxNumber',
'inetOrgPerson_street', 'inetOrgPerson_postalAddress')),
2012-05-25 18:22:43 +00:00
array('name' => _('Password'),
2006-08-03 18:02:21 +00:00
'fields' => array('posixAccount_password'))
);
2012-08-18 15:55:43 +00:00
$this->readOnlyFields = array();
2013-11-30 15:02:06 +00:00
$this->relabelFields = array();
2014-01-23 19:23:48 +00:00
$this->moduleSettings = array();
2014-02-02 16:32:39 +00:00
$this->language = 'en_GB.utf8';
$this->enforceLanguage = true;
2014-10-26 09:33:43 +00:00
$this->followReferrals = 0;
2015-11-07 09:14:48 +00:00
$this->timeZone = 'Europe/London';
2017-02-11 17:16:08 +00:00
$this->twoFactorAuthentication = TwoFactorProviderService::TWO_FACTOR_NONE;
2017-01-23 18:57:50 +00:00
$this->twoFactorAuthenticationURL = 'https://localhost';
$this->twoFactorAuthenticationInsecure = false;
2017-01-30 19:02:31 +00:00
$this->twoFactorAuthenticationLabel = null;
2017-01-31 19:50:51 +00:00
$this->twoFactorAuthenticationOptional = false;
$this->twoFactorAuthenticationCaption = '';
2019-01-01 09:54:31 +00:00
$this->twoFactorAuthenticationClientId = '';
$this->twoFactorAuthenticationSecretKey = '';
2019-08-11 07:39:47 +00:00
$this->twoFactorAuthenticationAttribute = 'uid';
2020-01-08 19:38:26 +00:00
$this->twoFactorAuthenticationDomain = '';
2018-02-10 16:31:03 +00:00
$this->captchaProvider = '-';
$this->reCaptchaSiteKey = '';
$this->reCaptchaSecretKey = '';
$this->captchaOnLogin = false;
2019-03-09 08:41:32 +00:00
$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);
}
2006-07-10 19:30:14 +00:00
}
2006-09-09 11:43:19 +00:00
2006-07-10 19:30:14 +00:00
}
2006-06-28 15:13:16 +00:00
?>