From 6647e4ccb89f63580897b332ce030c0f68b96c12 Mon Sep 17 00:00:00 2001 From: Joost van Dijk <argine@xs4all.nl> Date: Wed, 27 May 2015 01:07:51 +0200 Subject: [PATCH] add authentication processing filter for generating certificate expiry warnings --- .../dictionaries/X509warning.definition.json | 11 +++ .../dictionaries/X509warning.translation.json | 11 +++ modules/authX509/docs/authX509.txt | 14 ++++ .../lib/Auth/Process/ExpiryWarning.php | 84 +++++++++++++++++++ modules/authX509/templates/X509warning.php | 41 +++++++++ modules/authX509/www/expirywarning.php | 29 +++++++ 6 files changed, 190 insertions(+) create mode 100644 modules/authX509/dictionaries/X509warning.definition.json create mode 100644 modules/authX509/dictionaries/X509warning.translation.json create mode 100644 modules/authX509/lib/Auth/Process/ExpiryWarning.php create mode 100644 modules/authX509/templates/X509warning.php create mode 100644 modules/authX509/www/expirywarning.php diff --git a/modules/authX509/dictionaries/X509warning.definition.json b/modules/authX509/dictionaries/X509warning.definition.json new file mode 100644 index 000000000..4770dcf2c --- /dev/null +++ b/modules/authX509/dictionaries/X509warning.definition.json @@ -0,0 +1,11 @@ +{ + "warning": { + "en": "Your certificate will expire in %days% days. Please renew your certificate in time." + }, + "warning_header": { + "en": "Your certificate is about to expire." + }, + "proceed": { + "en": "Proceed" + } +} diff --git a/modules/authX509/dictionaries/X509warning.translation.json b/modules/authX509/dictionaries/X509warning.translation.json new file mode 100644 index 000000000..11ac94b55 --- /dev/null +++ b/modules/authX509/dictionaries/X509warning.translation.json @@ -0,0 +1,11 @@ +{ + "warning": { + "nl": "Je certificaat verloopt over %days% dagen. Vervang tijdig je certificaat." + }, + "warning_header": { + "nl": "Je certificaat verloopt binnenkort." + }, + "proceed": { + "nl": "Verder" + } +} diff --git a/modules/authX509/docs/authX509.txt b/modules/authX509/docs/authX509.txt index 8cb3ff352..f37c8ee25 100644 --- a/modules/authX509/docs/authX509.txt +++ b/modules/authX509/docs/authX509.txt @@ -106,3 +106,17 @@ can hack your metadata/saml20-idp-hosted.php file that way: 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri', ) +Checking certificate expiry +=========================== + +To issue warnings to users whos certificate is about to expire, configure an authproc filter. + +Example: + + 10 => array( + 'class' => 'authX509:ExpiryWarning', + 'warndaysbefore' => '30', + ), + +Parameter `warndaysbefore` specifies the number of days the user's certificate needs to be valid before a warning is +issued. The default is 30. \ No newline at end of file diff --git a/modules/authX509/lib/Auth/Process/ExpiryWarning.php b/modules/authX509/lib/Auth/Process/ExpiryWarning.php new file mode 100644 index 000000000..f9dedf573 --- /dev/null +++ b/modules/authX509/lib/Auth/Process/ExpiryWarning.php @@ -0,0 +1,84 @@ +<?php + +/** + * Filter which shows a warning if the user's client certificate is about to expire. + * + ** <code> + * // show about2xpire warning if client certificate is about to expire + * 10 => array( + * 'class' => 'authX509:ExpiryWarning', + * 'warndaysbefore' => '30', + * ), + * </code> + * + * @author Joost van Dijk, SURFnet. <Joost.vanDijk@surfnet.nl> + * @package simpleSAMLphp + */ +class sspmod_authX509_Auth_Process_ExpiryWarning extends SimpleSAML_Auth_ProcessingFilter { + + private $warndaysbefore = 30; + + /** + * 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 \'warndaysbefore\'-option to authX509::ExpiryWarning filter.'); + } + } + } + + /** + * Process an authentication response. + * + * This function saves the state, and if necessary redirects the user to the page where the user + * is informed about the expiry date of his/her certificate. + * + * @param array $state The state of the response. + */ + public function process(&$state) { + assert('is_array($state)'); + + if (isset($state['isPassive']) && $state['isPassive'] === TRUE) { + /* We have a passive request. Skip the warning. */ + return; + } + + if (!isset($_SERVER['SSL_CLIENT_CERT']) || + ($_SERVER['SSL_CLIENT_CERT'] == '')) { + return; + } + + $client_cert = $_SERVER['SSL_CLIENT_CERT']; + $client_cert_data = openssl_x509_parse($client_cert); + if ($client_cert_data == FALSE) { + SimpleSAML_Logger::error('authX509: invalid cert'); + return; + } + $validTo = $client_cert_data['validTo_time_t']; + $now = time(); + $daysleft = (int)(($validTo - $now) / (24*60*60)); + if ($daysleft > $this->warndaysbefore) { + /* We have a certificate that will be valid for some time. Skip the warning. */ + return; + } + + SimpleSAML_Logger::warning('authX509: user certificate expires in ' . $daysleft . ' days'); + $state['daysleft'] = $daysleft; + + /* Save state and redirect. */ + $id = SimpleSAML_Auth_State::saveState($state, 'warning:expire'); + $url = SimpleSAML_Module::getModuleURL('authX509/expirywarning.php'); + \SimpleSAML\Utils\HTTP::redirectTrustedURL($url, array('StateId' => $id)); + } + +} diff --git a/modules/authX509/templates/X509warning.php b/modules/authX509/templates/X509warning.php new file mode 100644 index 000000000..b391ddda2 --- /dev/null +++ b/modules/authX509/templates/X509warning.php @@ -0,0 +1,41 @@ +<?php + +/** + * Template form for X509 warnings. + * + * Parameters: + * - 'target': Target URL for the continue-button. + * - 'data': Parameters which should be included in the request. + * + * @package simpleSAMLphp + */ + +$warning = $this->t('{authX509:X509warning:warning}', array( + '%days%' => htmlspecialchars($this->data['daysleft']), +)); + +$this->data['header'] = $this->t('{authX509:X509warning:warning_header}'); +$this->data['autofocus'] = 'proceedbutton'; + +$this->includeAtTemplateBase('includes/header.php'); + +?> + +<form style="display: inline; margin: 0px; padding: 0px" action="<?php echo htmlspecialchars($this->data['target']); ?>"> + + <?php + // Embed hidden fields... + foreach ($this->data['data'] as $name => $value) { + echo('<input type="hidden" name="' . htmlspecialchars($name) . '" value="' . htmlspecialchars($value) . '" />'); + } + ?> + <p><?php echo $warning; ?></p> + + <input type="submit" name="proceed" id="proceedbutton" value="<?php echo htmlspecialchars($this->t('{authX509:X509warning:proceed}')) ?>" /> + +</form> + + +<?php + +$this->includeAtTemplateBase('includes/footer.php'); diff --git a/modules/authX509/www/expirywarning.php b/modules/authX509/www/expirywarning.php new file mode 100644 index 000000000..f09a425cc --- /dev/null +++ b/modules/authX509/www/expirywarning.php @@ -0,0 +1,29 @@ +<?php + +/** + * This script warns a user that his/her certificate is about to expire. + * + * @package simpleSAMLphp + */ + +SimpleSAML_Logger::info('AuthX509 - Showing expiry warning to user'); + +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, 'warning:expire'); + + +if (array_key_exists('proceed', $_REQUEST)) { + /* The user has pressed the proceed-button. */ + SimpleSAML_Auth_ProcessingChain::resumeProcessing($state); +} + +$globalConfig = SimpleSAML_Configuration::getInstance(); + +$t = new SimpleSAML_XHTML_Template($globalConfig, 'authX509:X509warning.php'); +$t->data['target'] = SimpleSAML_Module::getModuleURL('authX509/expirywarning.php'); +$t->data['data'] = array('StateId' => $id); +$t->data['daysleft'] = $state['daysleft']; +$t->show(); -- GitLab