diff --git a/modules/expirycheck/default-disable b/modules/expirycheck/default-disable new file mode 100644 index 0000000000000000000000000000000000000000..fa0bd82e2df7bd79d57593d35bc53c1f9d3ef71f --- /dev/null +++ b/modules/expirycheck/default-disable @@ -0,0 +1,3 @@ +This file indicates that the default state of this module +is disabled. To enable, create a file named enable in the +same directory as this file. diff --git a/modules/expirycheck/dictionaries/warning.definition.json b/modules/expirycheck/dictionaries/warning.definition.json new file mode 100644 index 0000000000000000000000000000000000000000..8201900038bf69ce662b9491653a01c113ce5ea6 --- /dev/null +++ b/modules/expirycheck/dictionaries/warning.definition.json @@ -0,0 +1,35 @@ +{ + "access_denied": { + "en": "You do not have access to this service" + }, + "no_access_to": { + "en": "Your account %NETID% has expired, access denied!" + }, + "contact_home": { + "en": "Access to services is controlled by your home organization. Please contact your local IT support for questions." + }, + "expiry_date_text": { + "en": "Expiration date:" + }, + "warning_header": { + "en": "Warning, your account %NETID% will expire in %DAYSLEFT% %DAYS%!" + }, + "warning_header_today": { + "en": "Warning, your account %NETID% will expire today!" + }, + "warning": { + "en": "Warning, your account %NETID% will expire in %DAYSLEFT% %DAYS%!" + }, + "warning_today": { + "en": "Warning, your account %NETID% will expire today!" + }, + "day": { + "en": "day" + }, + "days": { + "en": "days" + }, + "btn_continue": { + "en": "I am aware of this, continue..." + } +} diff --git a/modules/expirycheck/dictionaries/warning.translation.json b/modules/expirycheck/dictionaries/warning.translation.json new file mode 100644 index 0000000000000000000000000000000000000000..195225099e492f8344b250c20932ba419cbcbd49 --- /dev/null +++ b/modules/expirycheck/dictionaries/warning.translation.json @@ -0,0 +1,46 @@ +{ + "access_denied": { + "en": "You do not have access to this service", + "sl": "Dostop do storitve zavrnjen." + }, + "no_access_to": { + "en": "Your account %NETID% has expired, access denied!", + "sl": "Dostop zavrnjen, ker je va\u0161e uporabni\u0161ko (NetID) %NETID% ime poteklo!" + }, + "contact_home": { + "en": "Access to services is controlled by your home organization. Please contact your local IT support for questions.", + "sl": "Mo\u017enost dostopa do storitve ureja va\u0161a doma\u010da organizacija. Obrnite se na njihov oddelek za pomo\u010d uporabnikom." + }, + "expiry_date_text": { + "en": "Expiration date:", + "sl": "Datum poteka:" + }, + "warning_header": { + "en": "Warning, your account %NETID% will expire in %DAYSLEFT% %DAYS%!", + "sl": "Pozor! Va\u0161e uporabni\u0161ko ime (NetID) %NETID% bo poteklo \u010dez %DAYSLEFT% %DAYS%!" + }, + "warning_header_today": { + "en": "Warning, your account %NETID% will expire today!", + "sl": "Pozor! Va\u0161e uporabni\u0161ko ime (NetID) %NETID% pote\u010de danes!" + }, + "warning": { + "en": "Warning, your account %NETID% will expire in %DAYSLEFT% %DAYS%!", + "sl": "Pozor! Va\u0161e uporabni\u0161ko ime (NetID) %NETID% bo poteklo \u010dez %DAYSLEFT% %DAYS%!" + }, + "warning_today": { + "en": "Warning, your account %NETID% will expire today!", + "sl": "Pozor! Va\u0161e uporabni\u0161ko ime (NetID) %NETID% pote\u010de danes!" + }, + "day": { + "en": "day", + "sl": "dan" + }, + "days": { + "en": "days", + "sl": "dni" + }, + "btn_continue": { + "en": "I am aware of this, continue..." , + "sl": "Zavedam se tega, nadaljuj..." + } +} diff --git a/modules/expirycheck/docs/expirycheck.txt b/modules/expirycheck/docs/expirycheck.txt new file mode 100644 index 0000000000000000000000000000000000000000..fecf3b6e47c1572a6875542b45f0d0b85f0263c8 --- /dev/null +++ b/modules/expirycheck/docs/expirycheck.txt @@ -0,0 +1,48 @@ +expirycheck module +================== + +The expirycheck module validates user's expiry date attribute by showing +warning to the user whose NetID is about to expire or denying access if NetID +has already expired. + +The expirycheck module is implemented as an Authentication Processing Filter. +That means it can be configured in the global config.php file or the SP remote +or IdP hosted metadata. + +It is recommended to run the expirycheck module at the IdP, and configure the +filter to run before all the other filters you may have enabled. + +How to setup the expirycheck module +----------------------------------- + +First you need to enable the expirycheck module, touch an `enable` file, in the +expirycheck module: + + touch modules/expirycheck/enable + +Then you need to set filter parameters in your config.php file. + +Example: + + 10 => array( + 'class' => 'expirycheck:ExpiryDate', + 'netid_attr' => 'eduPersonPrincipalName', + 'expirydate_attr' => 'schacExpiryDate', + 'warndaysbefore' => '60', + 'date_format' => 'd.m.Y', + ), + + +Parameter netid_attr represents (ldap) attribute name which has user's NetID stored in it, +parameter expirydate_attr represents (ldap) attribute name which has user's expiry date +(date must be formated as YYYYMMDDHHMMSSZ, e.g. 20111011235959Z) stored in it. Those two +attributes needs to be part of the attribute set, which is retrived from ldap during +authentication process. +Parameter warndaysbefore set as a number, which represents how many days before expiry +date the "about to expire" warning will show to the user. +Parameter date_format defines date representation format. PHP Date() syntax +is used. More info: http://php.net/manual/en/function.date.php + +P.S. + +Comments and bug reports please send to Alex MihiÄŤinac <alexm@arnes.si> diff --git a/modules/expirycheck/lib/Auth/Process/ExpiryDate.php b/modules/expirycheck/lib/Auth/Process/ExpiryDate.php new file mode 100644 index 0000000000000000000000000000000000000000..65b8395f5df48636c065bda1350cd9291d66bffe --- /dev/null +++ b/modules/expirycheck/lib/Auth/Process/ExpiryDate.php @@ -0,0 +1,161 @@ +<?php + +/** + * Filter which show "about to expire" warning or deny access if netid is expired. + * + * Based on preprodwarning module by rnd.feide.no + * + * <code> + * // show about2xpire warning or deny access if netid is expired + * 10 => array( + * 'class' => 'expirycheck:ExpiryDate', + * 'netid_attr' => 'eduPersonPrincipalName', + * 'expirydate_attr' => 'schacExpiryDate', + * 'warndaysbefore' => '60', + * 'date_format' => 'd.m.Y', # php date syntax + * ), + * </code> + * + * @author Alex MihiÄŤinac, ARNES. <alexm@arnes.si> + * @package simpleSAMLphp + * @version $Id$ + */ + +class sspmod_expirycheck_Auth_Process_ExpiryDate extends SimpleSAML_Auth_ProcessingFilter { + + private $warndaysbefore = 0; + private $netid_attr = NULL; + private $expirydate_attr = NULL; + private $date_format = 'd.m.Y'; + + + /** + * Initialize this filter. + * + * @param array $config Configuration information about this filter. + * @param mixed $reserved For future use. + */ + public function __construct($config, $reserved) { + parent::__construct($config, $reserved); + + assert('is_array($config)'); + + if (array_key_exists('warndaysbefore', $config)) { + $this->warndaysbefore = $config['warndaysbefore']; + if (!is_string($this->warndaysbefore)) { + throw new Exception('Invalid value for number of days given to expirycheck::ExpiryDate filter.'); + } + } + + if (array_key_exists('netid_attr', $config)) { + $this->netid_attr = $config['netid_attr']; + if (!is_string($this->netid_attr)) { + throw new Exception('Invalid attribute name given as eduPersonPrincipalName to expirycheck::ExpiryDate filter.'); + } + } + + if (array_key_exists('expirydate_attr', $config)) { + $this->expirydate_attr = $config['expirydate_attr']; + if (!is_string($this->expirydate_attr)) { + throw new Exception('Invalid attribute name given as schacExpiryDate to expirycheck::ExpiryDate filter.'); + } + } + + if (array_key_exists('date_format', $config)) { + $this->date_format = $config['date_format']; + if (!is_string($this->date_format)) { + throw new Exception('Invalid date format given to expirycheck::ExpiryDate filter.'); + } + } + } + + /** + * Show expirational warning if remaining days is equal or under defined $warndaysbefore + * @param integer $expireOnDate + * @param integer $warndaysbefore + * @return bool + * + */ + public function shWarning(&$state, $expireOnDate, $warndaysbefore) { + #date_default_timezone_set('Europe/Ljubljana'); + $now = time(); + $end = $expireOnDate; + + if ($expireOnDate >= $now) { + $days = (int)(($end - $now) / (24*60*60)); + if ($days <= $warndaysbefore) { + $state['daysleft'] = $days; + return true; + } + } + return false; + } + + /** + * Check if given date is older than today + * @param integer $expireOnDate + * @return bool + * + */ + public function checkDate($expireOnDate) { + $now = time(); + $end = $expireOnDate; + + if ($now <= $end) { + return true; + } else { + return false; + } + + } + + /** + * Apply filter + * + * @param array &$state The current state. + */ + public function process(&$state) { + /* + * UTC format: 20090527080352Z + */ + $netId = $state['Attributes'][$this->netid_attr][0]; + $expireOnDate = strtotime($state['Attributes'][$this->expirydate_attr][0]); + + if (self::shWarning(&$state, $expireOnDate, $this->warndaysbefore)) { + assert('is_array($state)'); + if (isset($state['isPassive']) && $state['isPassive'] === TRUE) { + /* We have a passive request. Skip the warning. */ + return; + } + + SimpleSAML_Logger::warning('expirycheck: NetID ' . $netId . + ' is about to expire!'); + + /* Save state and redirect. */ + $state['expireOnDate'] = date($this->date_format, $expireOnDate); + $state['netId'] = $netId; + $id = SimpleSAML_Auth_State::saveState($state, 'expirywarning:about2expire'); + $url = SimpleSAML_Module::getModuleURL('expirycheck/about2expire.php'); + SimpleSAML_Utilities::redirect($url, array('StateId' => $id)); + } + + if (!self::checkDate($expireOnDate)) { + SimpleSAML_Logger::error('expirycheck: NetID ' . $netId . + ' has expired [' . date($this->date_format, $expireOnDate) . ']. Access denied!'); + $globalConfig = SimpleSAML_Configuration::getInstance(); + + /* Save state and redirect. */ + $state['expireOnDate'] = date($this->date_format, $expireOnDate); + $state['netId'] = $netId; + $id = SimpleSAML_Auth_State::saveState($state, 'expirywarning:expired'); + $url = SimpleSAML_Module::getModuleURL('expirycheck/expired.php'); + SimpleSAML_Utilities::redirect($url, array('StateId' => $id)); + + } + } + + +} + + +?> diff --git a/modules/expirycheck/templates/about2expire.php b/modules/expirycheck/templates/about2expire.php new file mode 100644 index 0000000000000000000000000000000000000000..eadb4bb86fe2dc46fe33871aa1c6db61214db9ae --- /dev/null +++ b/modules/expirycheck/templates/about2expire.php @@ -0,0 +1,93 @@ +<?php + +/** + * Template form for giving consent. + * + * Parameters: + * - 'srcMetadata': Metadata/configuration for the source. + * - 'dstMetadata': Metadata/configuration for the destination. + * - 'yesTarget': Target URL for the yes-button. This URL will receive a POST request. + * - 'yesData': Parameters which should be included in the yes-request. + * - 'noTarget': Target URL for the no-button. This URL will receive a GET request. + * - 'noData': Parameters which should be included in the no-request. + * - 'attributes': The attributes which are about to be released. + * - 'sppp': URL to the privacy policy of the destination, or FALSE. + * + * @package simpleSAMLphp + * @version $Id$ + */ + + +//$this->data['header'] = $this->t('{expirycheck:warning:warning_header}'); + +# netid will expire today +if ($this->data['daysleft'] == 0) { + $this->data['header'] = $this->t('{expirycheck:warning:warning_header_today}', array( + '%NETID%' => htmlspecialchars($this->data['netId']) + )); + + $warning = $this->t('{expirycheck:warning:warning_today}', array( + '%NETID%' => htmlspecialchars($this->data['netId']) + )); + +} +# netid will expire in one day +elseif ($this->data['daysleft'] == 1) { + + $this->data['header'] = $this->t('{expirycheck:warning:warning_header}', array( + '%NETID%' => htmlspecialchars($this->data['netId']), + '%DAYS%' => $this->t('{expirycheck:warning:day}'), + '%DAYSLEFT%' => htmlspecialchars($this->data['daysleft']), + )); + + $warning = $this->t('{expirycheck:warning:warning}', array( + '%NETID%' => htmlspecialchars($this->data['netId']), + '%DAYS%' => $this->t('{expirycheck:warning:day}'), + '%DAYSLEFT%' => htmlspecialchars($this->data['daysleft']), + )); + +} +# netid will expire in next <daysleft> days +else { + $this->data['header'] = $this->t('{expirycheck:warning:warning_header}', array( + '%NETID%' => htmlspecialchars($this->data['netId']), + '%DAYS%' => $this->t('{expirycheck:warning:days}'), + '%DAYSLEFT%' => htmlspecialchars($this->data['daysleft']), + )); + + $warning = $this->t('{expirycheck:warning:warning}', array( + '%NETID%' => htmlspecialchars($this->data['netId']), + '%DAYS%' => $this->t('{expirycheck:warning:days}'), + '%DAYSLEFT%' => htmlspecialchars($this->data['daysleft']), + )); + + +} + +//$this->data['header'] = str_replace("%DAYSLEFT%", $this->data['daysleft'], str_replace("%NETID%", $this->data['netId'], $this->t('{expirycheck:warning:warning_header}'))); +$this->data['autofocus'] = 'yesbutton'; + +$this->includeAtTemplateBase('includes/header.php'); + +?> + +<form style="display: inline; margin: 0px; padding: 0px" action="<?php echo htmlspecialchars($this->data['yesTarget']); ?>"> + + <?php + // Embed hidden fields... + foreach ($this->data['yesData'] as $name => $value) { + echo('<input type="hidden" name="' . htmlspecialchars($name) . '" value="' . htmlspecialchars($value) . '" />'); + } + ?> + <h3><?php echo $warning; ?></h3> + <p><?php echo $this->t('{expirycheck:warning:expiry_date_text}') . " " . $this->data['expireOnDate']; ?></p> + + <input type="submit" name="yes" id="yesbutton" value="<?php echo htmlspecialchars($this->t('{expirycheck:warning:btn_continue}')) ?>" /> + +</form> + + +<?php + +$this->includeAtTemplateBase('includes/footer.php'); +?> diff --git a/modules/expirycheck/templates/expired.php b/modules/expirycheck/templates/expired.php new file mode 100644 index 0000000000000000000000000000000000000000..0edd9aaad63e7fad059d9b1b935dab77ca7e0291 --- /dev/null +++ b/modules/expirycheck/templates/expired.php @@ -0,0 +1,12 @@ +<?php +$this->data['header'] = $this->t('{expirycheck:warning:access_denied}'); +$this->includeAtTemplateBase('includes/header.php'); +?> + + <h2><?php echo $this->t('{expirycheck:warning:access_denied}');?></h2> + <p><?php echo $this->t('{expirycheck:warning:no_access_to}', array('%NETID%' => htmlspecialchars($this->data['netId'])));?></p> + <p><?php echo $this->t('{expirycheck:warning:expiry_date_text}');?> <b><?php echo htmlspecialchars($this->data['expireOnDate']);?></b></p> + <p><?php echo $this->t('{expirycheck:warning:contact_home}');?></p> +<?php +$this->includeAtTemplateBase('includes/footer.php'); +?> diff --git a/modules/expirycheck/www/about2expire.php b/modules/expirycheck/www/about2expire.php new file mode 100644 index 0000000000000000000000000000000000000000..c69624723ac223fa571725031458ce2581eb1ba2 --- /dev/null +++ b/modules/expirycheck/www/about2expire.php @@ -0,0 +1,36 @@ +<?php + +/** + * about2expire.php + * + * @package simpleSAMLphp + * @version $Id$ + */ + +SimpleSAML_Logger::info('expirycheck - User has been warned that NetID is near to expirational date.'); + +if (!array_key_exists('StateId', $_REQUEST)) { + throw new SimpleSAML_Error_BadRequest('Missing required StateId query parameter.'); +} + +$id = $_REQUEST['StateId']; +$state = SimpleSAML_Auth_State::loadState($id, 'expirywarning:about2expire'); + + +if (array_key_exists('yes', $_REQUEST)) { + /* The user has pressed the yes-button. */ + SimpleSAML_Auth_ProcessingChain::resumeProcessing($state); +} + +$globalConfig = SimpleSAML_Configuration::getInstance(); + +$t = new SimpleSAML_XHTML_Template($globalConfig, 'expirycheck:about2expire.php'); +$t->data['yesTarget'] = SimpleSAML_Module::getModuleURL('expirycheck/about2expire.php'); +$t->data['yesData'] = array('StateId' => $id); +$t->data['daysleft'] = $state['daysleft']; +$t->data['expireOnDate'] = $state['expireOnDate']; +$t->data['netId'] = $state['netId']; +$t->show(); + + +?> diff --git a/modules/expirycheck/www/expired.php b/modules/expirycheck/www/expired.php new file mode 100644 index 0000000000000000000000000000000000000000..9b94cadbcec3a7df15f5e88aed680b7539571e69 --- /dev/null +++ b/modules/expirycheck/www/expired.php @@ -0,0 +1,27 @@ +<?php + +/** + * about2expire.php + * + * @package simpleSAMLphp + * @version $Id$ + */ + +SimpleSAML_Logger::info('expirycheck - User has been warned that NetID is near to expirational date.'); + +if (!array_key_exists('StateId', $_REQUEST)) { + throw new SimpleSAML_Error_BadRequest('Missing required StateId query parameter.'); +} + +$id = $_REQUEST['StateId']; +$state = SimpleSAML_Auth_State::loadState($id, 'expirywarning:expired'); + +$globalConfig = SimpleSAML_Configuration::getInstance(); + +$t = new SimpleSAML_XHTML_Template($globalConfig, 'expirycheck:expired.php'); +$t->data['expireOnDate'] = $state['expireOnDate']; +$t->data['netId'] = $state['netId']; +$t->show(); + + +?>