'Jan', '02' => 'Feb', '03' => 'Mar', '04' => 'Apr', '05' => 'May', '06' => 'Jun', '07' => 'Jul', '08' => 'Aug', '09' => 'Sep', '10' => 'Oct', '11' => 'Nov', '12' => 'Dec' ); /** cache for profile DNs */ private $profileCache = null; /** * Creates a new freeRadius object. * * @param string $scope account type (user, group, host) */ function __construct($scope) { parent::__construct($scope); $this->autoAddObjectClasses = false; } /** * Returns true if this module can manage accounts of the current type, otherwise false. * * @return boolean true if module fits */ public function can_manage() { return in_array($this->get_scope(), array('user')); } /** * Returns meta data that is interpreted by parent class * * @return array array with meta data * * @see baseModule::get_metaData() */ function get_metaData() { $return = array(); // icon $return['icon'] = 'freeRadius.png'; // alias name $return["alias"] = _("FreeRadius"); // module dependencies $return['dependencies'] = array('depends' => array(array('posixAccount', 'inetOrgPerson')), 'conflicts' => array()); // managed object classes $return['objectClasses'] = array('radiusprofile'); // managed attributes $return['attributes'] = array('radiusFramedIPAddress', 'radiusFramedIPNetmask', 'radiusRealm', 'radiusGroupName', 'radiusExpiration', 'radiusIdleTimeout', 'dialupAccess', 'radiusProfileDn'); // help Entries $return['help'] = array( 'radiusFramedIPAddress' => array( "Headline" => _("IP address"), 'attr' => 'radiusFramedIPAddress', "Text" => _("This is the IP address for the user (e.g. 123.123.123.123).") ), 'radiusFramedIPNetmask' => array( "Headline" => _("Net mask"), 'attr' => 'radiusFramedIPNetmask', "Text" => _("The net mask for the IP address.") ), 'radiusRealm' => array( "Headline" => _("Realm"), 'attr' => 'radiusRealm', "Text" => _("The Radius realm of this account.") ), 'radiusGroupName' => array( "Headline" => _("Group names"), 'attr' => 'radiusGroupName', "Text" => _("The group names for this account.") ), 'radiusGroupNameList' => array( "Headline" => _("Group names"), 'attr' => 'radiusGroupName', "Text" => _("The group names for this account.") . ' ' . _("Multiple values are separated by semicolon.") ), 'radiusExpiration' => array( "Headline" => _("Expiration date"), 'attr' => 'radiusExpiration', "Text" => _("The account will be locked after this date.") ), 'radiusIdleTimeout' => array( "Headline" => _("Idle timeout"), 'attr' => 'radiusIdleTimeout', "Text" => _("Specifies the maximum number of seconds that a connection can be idle before the session is terminated.") ), 'dialupAccess' => array( "Headline" => _("Enabled"), 'attr' => 'dialupAccess', "Text" => _("Specifies if the user may authenticate with FreeRadius.") ), 'profileDN' => array( "Headline" => _("Profile DN"), 'attr' => 'radiusProfileDn', "Text" => _('DN where Radius profile templates are stored.') ), 'radiusProfileDn' => array( "Headline" => _("Profile"), 'attr' => 'radiusProfileDn', "Text" => _('Radius profile for this user.') ), 'hiddenOptions' => array( "Headline" => _("Hidden options"), "Text" => _("The selected options will not be managed inside LAM. You can use this to reduce the number of displayed input fields.") )); // profile settings $profileElements = array(); if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusFramedIPNetmask')) { $profileElements[] = new htmlResponsiveInputField(_('Net mask'), 'freeRadius_radiusFramedIPNetmask', null, 'radiusFramedIPNetmask'); $return['profile_checks']['freeRadius_radiusFramedIPNetmask'] = array( 'type' => 'ext_preg', 'regex' => 'ip', 'error_message' => $this->messages['radiusFramedIPNetmask'][0]); $return['profile_mappings']['freeRadius_radiusFramedIPNetmask'] = 'radiusFramedIPNetmask'; } if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusRealm')) { $profileElements[] = new htmlResponsiveInputField(_('Realm'), 'freeRadius_radiusRealm', null, 'radiusRealm'); $return['profile_checks']['freeRadius_radiusRealm'] = array( 'type' => 'ext_preg', 'regex' => 'DNSname', 'error_message' => $this->messages['radiusRealm'][0]); $return['profile_mappings']['freeRadius_radiusRealm'] = 'radiusRealm'; } if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusGroupName')) { $profileElements[] = new htmlResponsiveInputField(_('Group names'), 'freeRadius_radiusGroupName', null, 'radiusGroupNameList'); } if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusIdleTimeout')) { $profileElements[] = new htmlResponsiveInputField(_('Idle timeout'), 'freeRadius_radiusIdleTimeout', null, 'radiusIdleTimeout'); $return['profile_checks']['freeRadius_radiusIdleTimeout'] = array( 'type' => 'ext_preg', 'regex' => 'digit', 'error_message' => $this->messages['radiusIdleTimeout'][0]); $return['profile_mappings']['freeRadius_radiusIdleTimeout'] = 'radiusIdleTimeout'; } if (!$this->isBooleanConfigOptionSet('freeRadius_hideDialupAccess')) { $enabledOptions = array('-' => '', _('Yes') => 'true', _('No') => 'false'); $dialupAccessSelect = new htmlResponsiveSelect('freeRadius_dialupAccess', $enabledOptions, array('true'), _('Enabled'), 'dialupAccess'); $dialupAccessSelect->setHasDescriptiveElements(true); $profileElements[] = $dialupAccessSelect; $return['profile_mappings']['freeRadius_dialupAccess'] = 'dialupAccess'; } if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusProfileDn') && isLoggedIn()) { $profileOptions = array('-' => ''); foreach ($this->getProfiles() as $dn) { $profileOptions[getAbstractDN($dn)] = $dn; } $profileSelect = new htmlResponsiveSelect('freeRadius_radiusProfileDn', $profileOptions, array(''), _('Profile'), 'radiusProfileDn'); $profileSelect->setHasDescriptiveElements(true); $profileElements[] = $profileSelect; $return['profile_mappings']['freeRadius_radiusProfileDn'] = 'radiusProfileDn'; } if (sizeof($profileElements) > 0) { $profileContainer = new htmlResponsiveRow(); for ($i = 0; $i < sizeof($profileElements); $i++) { $profileContainer->add($profileElements[$i], 12); } $return['profile_options'] = $profileContainer; } // upload fields $return['upload_columns'] = array(); if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusRealm')) { $return['upload_columns'][] = array( 'name' => 'freeRadius_radiusRealm', 'description' => _('Realm'), 'help' => 'radiusRealm', 'example' => _('company.com') ); } if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusGroupName')) { $return['upload_columns'][] = array( 'name' => 'freeRadius_radiusGroupName', 'description' => _('Group names'), 'help' => 'radiusGroupNameList', 'example' => _('group01;group02') ); } if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusFramedIPAddress')) { $return['upload_columns'][] = array( 'name' => 'freeRadius_radiusFramedIPAddress', 'description' => _('IP address'), 'help' => 'radiusFramedIPAddress', 'example' => '123.123.123.123', ); } if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusFramedIPNetmask')) { $return['upload_columns'][] = array( 'name' => 'freeRadius_radiusFramedIPNetmask', 'description' => _('Net mask'), 'help' => 'radiusFramedIPNetmask', 'example' => '255.255.255.0' ); } if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusExpiration')) { $return['upload_columns'][] = array( 'name' => 'freeRadius_radiusExpiration', 'description' => _('Expiration date'), 'help' => 'radiusExpiration', 'example' => '17.07.2017 00:00' ); } if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusIdleTimeout')) { $return['upload_columns'][] = array( 'name' => 'freeRadius_radiusIdleTimeout', 'description' => _('Idle timeout'), 'help' => 'radiusIdleTimeout', 'example' => '3600' ); } if (!$this->isBooleanConfigOptionSet('freeRadius_hideDialupAccess')) { $return['upload_columns'][] = array( 'name' => 'freeRadius_dialupAccess', 'description' => _('Enabled'), 'help' => 'dialupAccess', 'example' => 'true', 'values' => 'true, false' ); } if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusProfileDn')) { $return['upload_columns'][] = array( 'name' => 'freeRadius_radiusProfileDn', 'description' => _('Profile'), 'help' => 'radiusProfileDn', 'example' => 'cn=profile,ou=radiusProfile,dc=example,dc=com' ); } // available PDF fields $return['PDF_fields'] = array(); if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusFramedIPAddress')) { $return['PDF_fields']['radiusFramedIPAddress'] = _('IP address'); } if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusFramedIPNetmask')) { $return['PDF_fields']['radiusFramedIPNetmask'] = _('Net mask'); } if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusRealm')) { $return['PDF_fields']['radiusRealm'] = _('Realm'); } if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusGroupName')) { $return['PDF_fields']['radiusGroupName'] = _('Group names'); } if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusExpiration')) { $return['PDF_fields']['radiusExpiration'] = _('Expiration date'); } if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusIdleTimeout')) { $return['PDF_fields']['radiusIdleTimeout'] = _('Idle timeout'); } if (!$this->isBooleanConfigOptionSet('freeRadius_hideDialupAccess')) { $return['PDF_fields']['dialupAccess'] = _('Enabled'); } if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusProfileDn')) { $return['PDF_fields']['radiusProfileDn'] = _('Profile'); } return $return; } /** * Returns a list of configuration options. * * Calling this method does not require the existence of an enclosing {@link accountContainer}.
*
* The field names are used as keywords to load and save settings. * We recommend to use the module name as prefix for them (e.g. posixAccount_homeDirectory) to avoid naming conflicts. * * @param array $scopes account types (user, group, host) * @param array $allScopes list of all active account modules and their scopes (module => array(scopes)) * @return mixed htmlElement or array of htmlElement * * @see htmlElement */ public function get_configOptions($scopes, $allScopes) { $configContainer = new htmlResponsiveRow(); $configContainer->add(new htmlResponsiveInputField(_('Profile DN'), 'freeRadius_profileDN', '', 'profileDN'), 12); $configContainer->addVerticalSpacer('1rem'); $hiddenGroup = new htmlGroup(); $hiddenGroup->addElement(new htmlOutputText(_('Hidden options'))); $hiddenGroup->addElement(new htmlHelpLink('hiddenOptions')); $configContainer->add($hiddenGroup, 12); $configContainer->addVerticalSpacer('0.5rem'); $configContainer->add(new htmlResponsiveInputCheckbox('freeRadius_hideRadiusFramedIPAddress', false, _('IP address'), null, true), 12, 4); $configContainer->add(new htmlResponsiveInputCheckbox('freeRadius_hideRadiusFramedIPNetmask', false, _('Net mask'), null, true), 12, 4); $configContainer->add(new htmlResponsiveInputCheckbox('freeRadius_hideRadiusRealm', false, _('Realm'), null, true), 12, 4); $configContainer->add(new htmlResponsiveInputCheckbox('freeRadius_hideRadiusGroupName', false, _('Group names'), null, true), 12, 4); $configContainer->add(new htmlResponsiveInputCheckbox('freeRadius_hideRadiusExpiration', false, _('Expiration date'), null, true), 12, 4); $configContainer->add(new htmlResponsiveInputCheckbox('freeRadius_hideRadiusIdleTimeout', false, _('Idle timeout'), null, true), 12, 4); $configContainer->add(new htmlResponsiveInputCheckbox('freeRadius_hideRadiusProfileDn', false, _('Profile'), null, true), 12, 4); $configContainer->add(new htmlResponsiveInputCheckbox('freeRadius_hideDialupAccess', false, _('Enabled'), null, true), 12, 4); return $configContainer; } /** * This function fills the error message array with messages */ function load_Messages() { $this->messages['radiusFramedIPAddress'][0] = array('ERROR', _('The IP address is invalid.')); $this->messages['radiusFramedIPAddress'][1] = array('ERROR', _('Account %s:') . ' freeRadius_radiusFramedIPAddress', _('The IP address is invalid.')); $this->messages['radiusFramedIPNetmask'][0] = array('ERROR', _('The net mask is invalid.')); $this->messages['radiusFramedIPNetmask'][1] = array('ERROR', _('Account %s:') . ' freeRadius_radiusFramedIPNetmask', _('The net mask is invalid.')); $this->messages['radiusRealm'][0] = array('ERROR', _('Please enter a valid realm.')); $this->messages['radiusRealm'][1] = array('ERROR', _('Account %s:') . ' freeRadius_radiusRealm', _('Please enter a valid realm.')); $this->messages['radiusGroupName'][0] = array('ERROR', _('Please enter a valid list of group names.')); $this->messages['radiusGroupName'][1] = array('ERROR', _('Account %s:') . ' freeRadius_radiusGroupName', _('Please enter a valid list of group names.')); $this->messages['radiusExpiration'][0] = array('ERROR', _('The expiration date must be in format DD.MM.YYYY HH:MM.')); $this->messages['radiusExpiration'][1] = array('ERROR', _('Account %s:') . ' freeRadius_radiusExpiration', _('The expiration date must be in format DD.MM.YYYY HH:MM.')); $this->messages['radiusIdleTimeout'][0] = array('ERROR', _('Please enter a numeric value for the idle timeout.')); $this->messages['radiusIdleTimeout'][1] = array('ERROR', _('Account %s:') . ' freeRadius_radiusIdleTimeout', _('Please enter a numeric value for the idle timeout.')); $this->messages['dialupAccess'][0] = array('ERROR', _('Account %s:') . ' freeRadius_dialupAccess', _('This value can only be "true" or "false".')); $this->messages['radiusProfileDn'][0] = array('ERROR', _('Account %s:') . ' freeRadius_radiusProfileDn', _('This is not a valid DN!')); } /** * Returns the HTML meta data for the main account page. * * @return htmlElement HTML meta data */ function display_html_attributes() { $return = new htmlResponsiveRow(); if (in_array('radiusprofile', $this->attributes['objectClass'])) { // realm if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusRealm')) { $this->addSimpleInputTextField($return, 'radiusRealm', _('Realm')); } // group names if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusGroupName')) { $this->addMultiValueInputTextField($return, 'radiusGroupName', _('Group names')); } // IP address if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusFramedIPAddress')) { $this->addSimpleInputTextField($return, 'radiusFramedIPAddress', _('IP address')); } // net mask if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusFramedIPNetmask')) { $this->addSimpleInputTextField($return, 'radiusFramedIPNetmask', _('Net mask')); } // idle timeout if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusIdleTimeout')) { $radiusIdleTimeoutInput = $this->addSimpleInputTextField($return, 'radiusIdleTimeout', _('Idle timeout')); $radiusIdleTimeoutInput->setValidationRule(htmlElement::VALIDATE_NUMERIC); } // expiration date if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusExpiration')) { $radiusExpiration = '  -'; if (isset($this->attributes['radiusExpiration'][0])) { $radiusExpiration = $this->formatExpirationDate($this->attributes['radiusExpiration'][0]); } $return->addLabel(new htmlOutputText('Expiration date')); $radiusExpirationList = new htmlGroup(); $radiusExpirationList->addElement(new htmlOutputText($radiusExpiration . '     ', false)); $radiusExpirationList->addElement(new htmlAccountPageButton(get_class($this), 'expiration', 'change', _('Change'))); $radiusExpirationList->addElement(new htmlHelpLink('radiusExpiration')); $return->addField($radiusExpirationList); } // profile DN if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusProfileDn')) { $profiles = array('-' => '-'); foreach ($this->getProfiles() as $dn) { $profiles[getAbstractDN($dn)] = $dn; } $profile = array(); if (!empty($this->attributes['radiusProfileDn'][0])) { $profile = $this->attributes['radiusProfileDn']; if (!in_array($this->attributes['radiusProfileDn'][0], $profiles)) { $profiles[getAbstractDN($this->attributes['radiusProfileDn'][0])] = $this->attributes['radiusProfileDn'][0]; } } $profileSelect = new htmlResponsiveSelect('radiusProfileDn', $profiles, $profile, _('Profile'), 'radiusProfileDn'); $profileSelect->setHasDescriptiveElements(true); $return->add($profileSelect, 12); } // enabled if (!$this->isBooleanConfigOptionSet('freeRadius_hideDialupAccess')) { $enabled = array(''); if (!empty($this->attributes['dialupAccess'][0])) { $enabled = array($this->attributes['dialupAccess'][0]); // value in LDAP may be anything other than "false" to count as "true" if (!in_array($this->attributes['dialupAccess'][0], array('true', 'false', 'TRUE', 'FALSE'))) { $enabled = array('true'); } } $enabledOptions = array('-' => '', _('Yes') => 'true', _('No') => 'false'); $enabledSelect = new htmlResponsiveSelect('dialupAccess', $enabledOptions, $enabled, _('Enabled'), 'dialupAccess'); $enabledSelect->setHasDescriptiveElements(true); $return->add($enabledSelect, 12); } // button to remove extension $return->addVerticalSpacer('2rem'); $remButton = new htmlButton('remObjectClass', _('Remove FreeRadius extension')); $return->add($remButton, 12, 12, 12, 'text-center'); } else { $return->add(new htmlButton('addObjectClass', _('Add FreeRadius extension')), 12); } return $return; } /** * 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 */ function process_attributes() { if (isset($_POST['addObjectClass'])) { $this->attributes['objectClass'][] = 'radiusprofile'; return array(); } elseif (isset($_POST['remObjectClass'])) { $this->attributes['objectClass'] = array_delete(array('radiusprofile'), $this->attributes['objectClass']); for ($i = 0; $i < sizeof($this->meta['attributes']); $i++) { if (isset($this->attributes[$this->meta['attributes'][$i]])) { unset($this->attributes[$this->meta['attributes'][$i]]); } } return array(); } // skip processing if extension is not active if (!in_array('radiusprofile', $this->attributes['objectClass'])) { return array(); } $errors = array(); // IP address if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusFramedIPAddress')) { $this->attributes['radiusFramedIPAddress'][0] = $_POST['radiusFramedIPAddress']; if (($_POST['radiusFramedIPAddress'] != '') && !get_preg($_POST['radiusFramedIPAddress'], 'ip')) { $errors[] = $this->messages['radiusFramedIPAddress'][0]; } } // net mask if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusFramedIPNetmask')) { $this->attributes['radiusFramedIPNetmask'][0] = $_POST['radiusFramedIPNetmask']; if (($_POST['radiusFramedIPNetmask'] != '') && !get_preg($_POST['radiusFramedIPNetmask'], 'ip')) { $errors[] = $this->messages['radiusFramedIPNetmask'][0]; } } // realm if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusRealm')) { $this->attributes['radiusRealm'][0] = $_POST['radiusRealm']; if (($_POST['radiusRealm'] != '') && !get_preg($_POST['radiusRealm'], 'DNSname')) { $errors[] = $this->messages['radiusRealm'][0]; } } // group names if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusGroupName')) { $this->processMultiValueInputTextField('radiusGroupName', $errors, 'groupname'); } // idle timeout if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusIdleTimeout')) { $this->attributes['radiusIdleTimeout'][0] = $_POST['radiusIdleTimeout']; if (($_POST['radiusIdleTimeout'] != '') && !get_preg($_POST['radiusIdleTimeout'], 'digit')) { $errors[] = $this->messages['radiusIdleTimeout'][0]; } } // enabled if (!$this->isBooleanConfigOptionSet('freeRadius_hideDialupAccess')) { if (!empty($this->attributes['dialupAccess']) && ($_POST['dialupAccess'] === '')) { unset($this->attributes['dialupAccess']); } elseif ($_POST['dialupAccess'] === 'false') { $this->attributes['dialupAccess'][0] = 'false'; } elseif ($_POST['dialupAccess'] === 'true') { $this->attributes['dialupAccess'][0] = 'true'; } } // profile DN if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusProfileDn')) { if (($_POST['radiusProfileDn'] == '-') && !empty($this->attributes['radiusProfileDn'])) { unset($this->attributes['radiusProfileDn']); } elseif ($_POST['radiusProfileDn'] != '-') { $this->attributes['radiusProfileDn'][0] = $_POST['radiusProfileDn']; } } return $errors; } /** * This function will create the meta HTML code to show a page to change the expiration date. * * @return htmlElement meta HTML code */ function display_html_expiration() { $return = new htmlResponsiveRow(); $attr = 'radiusExpiration'; $text = _('Expiration date'); $help = "radiusExpiration"; $date = new DateTime('@' . (time() + 3600*24*365), new DateTimeZone('UTC')); $year = $date->format('Y'); $month = $date->format('m'); $month = self::$monthList[$month]; $day = $date->format('d'); $hour = '00'; $minute = '00'; if (isset($this->attributes[$attr][0]) && ($this->attributes[$attr][0] != '')) { $parts = explode(' ', $this->attributes[$attr][0]); $year = $parts[2]; $month = $parts[1]; $day = $parts[0]; if (isset($parts[3])) { $timeParts = explode(':', $parts[3]); $hour = $timeParts[0]; $minute = $timeParts[1]; } } for ( $i=0; $i<=59; $i++ ) { $minuteList[] = str_pad($i, 2, '0', STR_PAD_LEFT); } for ( $i=0; $i<=23; $i++ ) { $hourList[] = str_pad($i, 2, '0', STR_PAD_LEFT); } for ( $i=1; $i<=31; $i++ ) { $dayList[] = str_pad($i, 2, '0', STR_PAD_LEFT); } for ( $i=2003; $i<=2050; $i++ ) { $yearList[] = $i; } $return->addLabel(new htmlOutputText($text)); $dateGroup = new htmlGroup(); $daySelect = new htmlSelect('expire_day', $dayList, array($day)); $daySelect->setWidth('3rem'); $dateGroup->addElement($daySelect); $monthSelect = new htmlSelect('expire_mon', self::$monthList, array($month)); $monthSelect->setHasDescriptiveElements(true); $monthSelect->setWidth('3rem'); $dateGroup->addElement($monthSelect); $yearSelect = new htmlSelect('expire_yea', $yearList, array($year)); $yearSelect->setWidth('5rem'); $dateGroup->addElement($yearSelect); $dateGroup->addElement(new htmlSpacer('10px', null)); $hourSelect = new htmlSelect('expire_hour', $hourList, array($hour)); $hourSelect->setWidth('3rem'); $dateGroup->addElement($hourSelect); $minuteSelect = new htmlSelect('expire_minute', $minuteList, array($minute)); $minuteSelect->setWidth('3rem'); $dateGroup->addElement($minuteSelect); $dateGroup->addElement(new htmlHelpLink($help)); $return->addField($dateGroup); $return->addVerticalSpacer('2rem'); $buttons = new htmlGroup(); $buttons->addElement(new htmlAccountPageButton(get_class($this), 'attributes', 'change' . $attr, _('Change'))); $buttons->addElement(new htmlSpacer('0.5rem', null)); if (isset($this->attributes[$attr][0])) { $buttons->addElement(new htmlAccountPageButton(get_class($this), 'attributes', 'del' . $attr, _('Remove'))); $buttons->addElement(new htmlSpacer('0.5rem', null)); } $buttons->addElement(new htmlAccountPageButton(get_class($this), 'attributes', 'back' . $attr, _('Cancel'))); $return->add($buttons, 12); return $return; } /** * Processes user input of the time selection page. * * @return array list of info/error messages */ function process_expiration() { $return = array(); // find button name $buttonName = ''; $postKeys = array_keys($_POST); for ($i = 0; $i < sizeof($postKeys); $i++) { if (strpos($postKeys[$i], 'form_subpage_freeRadius_attributes_') !== false) { $buttonName = $postKeys[$i]; } } if (($buttonName == '') || (strpos($buttonName, '_back') !== false)) return array(); // get attribute name $attr = ''; if (strpos($buttonName, 'radiusExpiration') !== false) { $attr = 'radiusExpiration'; } if ($attr == '') return array(); // determine action if (strpos($buttonName, '_change') !== false) { // set new expiration date $this->attributes[$attr][0] = $_POST['expire_day'] . ' ' . $_POST['expire_mon'] . ' ' . $_POST['expire_yea'] . ' ' . $_POST['expire_hour'] . ':' . $_POST['expire_minute']; } elseif (strpos($buttonName, '_del') !== false) { // remove attribute value unset($this->attributes[$attr]); } return $return; } /** * Returns a list of modifications which have to be made to the LDAP account. * * @return array list of modifications *
This function returns an array with 3 entries: *
array( DN1 ('add' => array($attr), 'remove' => array($attr), 'modify' => array($attr)), DN2 .... ) *
DN is the DN to change. It may be possible to change several DNs (e.g. create a new user and add him to some groups via attribute memberUid) *
"add" are attributes which have to be added to LDAP entry *
"remove" are attributes which have to be removed from LDAP entry *
"modify" are attributes which have to been modified in LDAP entry *
"info" are values with informational value (e.g. to be used later by pre/postModify actions) */ function save_attributes() { if (!in_array('radiusprofile', $this->attributes['objectClass']) && !in_array('radiusprofile', $this->orig['objectClass'])) { // skip saving if the extension was not added/modified return array(); } return parent::save_attributes(); } /** * {@inheritDoc} * @see baseModule::build_uploadAccounts() */ function build_uploadAccounts($rawAccounts, $ids, &$partialAccounts, $selectedModules, &$type) { $errors = array(); for ($i = 0; $i < sizeof($rawAccounts); $i++) { // add object class if (!in_array("radiusprofile", $partialAccounts[$i]['objectClass'])) $partialAccounts[$i]['objectClass'][] = "radiusprofile"; // IP address $this->mapSimpleUploadField($rawAccounts, $ids, $partialAccounts, $i, 'freeRadius_radiusFramedIPAddress', 'radiusFramedIPAddress', 'ip', $this->messages['radiusFramedIPAddress'][1], $errors); // net mask $this->mapSimpleUploadField($rawAccounts, $ids, $partialAccounts, $i, 'freeRadius_radiusFramedIPNetmask', 'radiusFramedIPNetmask', 'ip', $this->messages['radiusFramedIPNetmask'][1], $errors); // realm $this->mapSimpleUploadField($rawAccounts, $ids, $partialAccounts, $i, 'freeRadius_radiusRealm', 'radiusRealm', 'DNSname', $this->messages['radiusRealm'][1], $errors); // group names $this->mapSimpleUploadField($rawAccounts, $ids, $partialAccounts, $i, 'freeRadius_radiusGroupName', 'radiusGroupName', 'groupname', $this->messages['radiusGroupName'][1], $errors, '/;[ ]*/'); // expiration date if ($rawAccounts[$i][$ids['freeRadius_radiusExpiration']] != "") { if (preg_match('/^[0-9]{1,2}.[0-9]{1,2}.[0-9]{4} [0-9]{1,2}:[0-9]{1,2}$/', $rawAccounts[$i][$ids['freeRadius_radiusExpiration']])) { $dateParts = explode(' ', $rawAccounts[$i][$ids['freeRadius_radiusExpiration']]); $dateParts1 = explode('.', $dateParts[0]); $radiusExpiration = str_pad($dateParts1[0], 2, '0', STR_PAD_LEFT) . ' ' . self::$monthList[str_pad($dateParts1[1], 2, '0', STR_PAD_LEFT)] . ' ' . $dateParts1[2]; $dateParts2 = explode(':', $dateParts[1]); $radiusExpiration .= ' ' . str_pad($dateParts2[0], 2, '0', STR_PAD_LEFT) . ':' . str_pad($dateParts2[1], 2, '0', STR_PAD_LEFT); $partialAccounts[$i]['radiusExpiration'] = $radiusExpiration; } else { $errMsg = $this->messages['radiusExpiration'][1]; array_push($errMsg, array($i)); $errors[] = $errMsg; } } // idle timeout $this->mapSimpleUploadField($rawAccounts, $ids, $partialAccounts, $i, 'freeRadius_radiusIdleTimeout', 'radiusIdleTimeout', 'digit', $this->messages['radiusIdleTimeout'][1], $errors); // enabled if (!empty($rawAccounts[$i][$ids['freeRadius_dialupAccess']])) { if (in_array($rawAccounts[$i][$ids['freeRadius_dialupAccess']], array('true', 'false'))) { $partialAccounts[$i]['dialupAccess'] = $rawAccounts[$i][$ids['freeRadius_dialupAccess']]; } else { $errMsg = $this->messages['dialupAccess'][0]; array_push($errMsg, array($i)); $errors[] = $errMsg; } } // profile DN $this->mapSimpleUploadField($rawAccounts, $ids, $partialAccounts, $i, 'freeRadius_radiusProfileDn', 'radiusProfileDn', 'dn', $this->messages['radiusProfileDn'][0], $errors); } return $errors; } /** * {@inheritDoc} * @see baseModule::get_pdfEntries() */ function get_pdfEntries($pdfKeys, $typeId) { $return = array(); $this->addSimplePDFField($return, 'radiusFramedIPAddress', _('IP address')); $this->addSimplePDFField($return, 'radiusFramedIPNetmask', _('Net mask')); $this->addSimplePDFField($return, 'radiusRealm', _('Realm')); $this->addSimplePDFField($return, 'radiusGroupName', _('Group names')); $this->addSimplePDFField($return, 'radiusIdleTimeout', _('Idle timeout')); $this->addSimplePDFField($return, 'radiusProfileDn', _('Profile')); if (isset($this->attributes['radiusExpiration'][0])) { $this->addPDFKeyValue($return, 'radiusExpiration', _('Expiration date'), $this->formatExpirationDate($this->attributes['radiusExpiration'][0])); } if (isset($this->attributes['dialupAccess'][0])) { $enabled = _('Yes'); if (in_array($this->attributes['dialupAccess'][0], array('false', 'FALSE'))) { $enabled = _('No'); } $this->addPDFKeyValue($return, 'dialupAccess', _('Enabled'), $enabled); } return $return; } /** * {@inheritDoc} */ function check_profileOptions($options, $typeId) { $messages = parent::check_profileOptions($options, $typeId); // group names if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusGroupName') && isset($options['freeRadius_radiusGroupName'][0]) && ($options['freeRadius_radiusGroupName'][0] != '')) { $list = preg_split('/;[ ]*/', $options['freeRadius_radiusGroupName'][0]); for ($i = 0; $i < sizeof($list); $i++) { if (!get_preg($list[$i], 'groupname')) { $messages[] = $this->messages['radiusGroupName'][0]; break; } } } return $messages; } /** * Loads the values of an account profile into internal variables. * * @param array $profile hash array with profile values (identifier => value) */ function load_profile($profile) { // profile mappings in meta data parent::load_profile($profile); // group names if (!$this->isBooleanConfigOptionSet('freeRadius_hideRadiusGroupName') && isset($profile['freeRadius_radiusGroupName'][0]) && ($profile['freeRadius_radiusGroupName'][0] != '')) { $this->attributes['radiusGroupName'] = preg_split('/;[ ]*/', $profile['freeRadius_radiusGroupName'][0]); } } /** * Formats the expiration date attribute. * * @param String $date date value */ private function formatExpirationDate($date) { if (is_null($date) || ($date == '')) { return $date; } foreach (self::$monthList as $replace => $search) { $date = str_replace($search, $replace, $date); } $dateParts = explode(' ', $date); $date = $dateParts[0] . '.' . $dateParts[1] . '.' . $dateParts[2]; if (isset($dateParts[3])) { $date .= ' ' . $dateParts[3]; } return $date; } /** * Returns a list of possible profile DNs. * * @return array list of profile DNs */ private function getProfiles() { if ($this->profileCache != null) { return $this->profileCache; } if (empty($this->moduleSettings['freeRadius_profileDN'][0])) { return array(); } $list = searchLDAP($this->moduleSettings['freeRadius_profileDN'][0], '(objectClass=radiusProfile)', array('dn')); foreach ($list as $attr) { $this->profileCache[] = $attr['dn']; } usort($this->profileCache, 'compareDN'); return $this->profileCache; } /** * Returns a list of jobs that can be run. * * @param LAMConfig $config configuration * @return array list of jobs */ public function getSupportedJobs(&$config) { return array( new FreeRadiusAccountExpirationCleanupJob(), new FreeRadiusAccountExpirationNotifyJob() ); } } if (interface_exists('\LAM\JOB\Job', false)) { include_once dirname(__FILE__) . '/../passwordExpirationJob.inc'; /** * Job to delete or move users on account expiration. * * @package jobs */ class FreeRadiusAccountExpirationCleanupJob extends \LAM\JOB\AccountExpirationCleanupJob { /** * Returns the alias name of the job. * * @return String name */ public function getAlias() { return _('FreeRadius') . ': ' . _('Cleanup expired user accounts'); } /** * Returns the description of the job. * * @return String description */ public function getDescription() { return _('This job deletes or moves user accounts when they expire.'); } /** * Searches for users in LDAP. * * @param String $jobID unique job identifier * @param array $options config options (name => value) * @return array list of user attributes */ protected function findUsers($jobID, $options) { // read users $attrs = array('radiusExpiration'); return searchLDAPByFilter('(radiusExpiration=*)', $attrs, array('user')); } /** * Checks if a user is expired. * * @param integer $jobID job ID * @param array $options job settings * @param PDO $pdo PDO * @param DateTime $now current time * @param array $policyOptions list of policy options by getPolicyOptions() * @param array $user user attributes * @param boolean $isDryRun just do a dry run, nothing is modified */ protected function checkSingleUser($jobID, $options, &$pdo, $now, $policyOptions, $user, $isDryRun) { $expireTime = DateTime::createFromFormat('d M Y H:i', $user['radiusexpiration'][0], new DateTimeZone('UTC')); $this->jobResultLog->logDebug("Expiration on " . $expireTime->format('Y-m-d')); $delay = 0; if (!empty($options[$this->getConfigPrefix() . '_delay' . $jobID][0])) { $delay = $options[$this->getConfigPrefix() . '_delay' . $jobID][0]; } $actionTime = clone $expireTime; if ($delay != 0) { $actionTime->add(new DateInterval('P' . $delay . 'D')); } $actionTime->setTimeZone(getTimeZone()); $this->jobResultLog->logDebug("Action time on " . $actionTime->format('Y-m-d')); if ($actionTime <= $now) { $this->performAction($jobID, $options, $user, $isDryRun); } } } /** * Job to notify users about account expiration. * * @package jobs */ class FreeRadiusAccountExpirationNotifyJob extends \LAM\JOB\PasswordExpirationJob { /** * {@inheritDoc} * @see \LAM\JOB\Job::getAlias() */ public function getAlias() { return _('FreeRadius') . ': ' . _('Notify users about account expiration'); } /** * {@inheritDoc} * @see \LAM\JOB\PasswordExpirationJob::getDescription() */ public function getDescription() { return _('This job sends out emails to inform your users that their account will expire soon.'); } /** * {@inheritDoc} * @see \LAM\JOB\PasswordExpirationJob::findUsers() */ protected function findUsers($jobID, $options) { // read users $sysattrs = array('radiusExpiration', 'mail'); $attrs = $this->getAttrWildcards($jobID, $options); $attrs = array_values(array_unique(array_merge($attrs, $sysattrs))); return searchLDAPByFilter('(&(radiusExpiration=*)(mail=*))', $attrs, array('user')); } /** * {@inheritDoc} * @see \LAM\JOB\PasswordExpirationJob::checkSingleUser() */ protected function checkSingleUser($jobID, $options, &$pdo, $now, $policyOptions, $user, $isDryRun) { $dn = $user['dn']; // get time when account expires $expirationTime = DateTime::createFromFormat('d M Y H:i', $user['radiusexpiration'][0], new DateTimeZone('UTC')); $this->jobResultLog->logDebug("Account expiration on " . $expirationTime->format('Y-m-d')); // skip if account itself is expired if ($expirationTime <= $now) { $this->jobResultLog->logDebug($dn . ' already expired'); return; } $numDaysToWarn = $options[$this->getConfigPrefix() . '_mailNotificationPeriod' . $jobID][0]; $this->jobResultLog->logDebug("Number of days before warning " . $numDaysToWarn); // calculate time of notification $notifyTime = clone $expirationTime; $notifyTime->sub(new DateInterval('P' . $numDaysToWarn . 'D')); $notifyTime->setTimeZone(getTimeZone()); $this->jobResultLog->logDebug("Account expiration notification on " . $notifyTime->format('Y-m-d H:i')); // skip if notification is in the future if ($notifyTime > $now) { $this->jobResultLog->logDebug($dn . ' does not need notification yet.'); return; } $dbLastChange = $this->getDBLastPwdChangeTime($jobID, $pdo, $dn); // skip entries where mail was already sent if ($dbLastChange == $user['radiusexpiration'][0]) { $this->jobResultLog->logDebug($dn . ' was already notified.'); return; } if ($isDryRun) { // no action for dry run $this->jobResultLog->logInfo('Not sending email to ' . $dn . ' because of dry run.'); return; } // send email $success = $this->sendMail($options, $jobID, $user, $expirationTime); // update DB if mail was sent successfully if ($success) { $this->setDBLastPwdChangeTime($jobID, $pdo, $dn, $user['radiusexpiration'][0]); } } } } ?>