From f0c4c64b849bb1de45ec702a56cd195801096901 Mon Sep 17 00:00:00 2001
From: Tim van Dijen <tim.dijen@minbzk.nl>
Date: Mon, 18 Feb 2019 10:26:03 +0100
Subject: [PATCH] Externalize CDC-module

---
 bin/build-release.sh                        |   5 +-
 modules/cdc/config-templates/module_cdc.php |  22 -
 modules/cdc/default-disable                 |   3 -
 modules/cdc/lib/Auth/Process/CDC.php        |  74 ----
 modules/cdc/lib/Client.php                  |  70 ----
 modules/cdc/lib/Server.php                  | 426 --------------------
 modules/cdc/www/resume.php                  |  20 -
 modules/cdc/www/server.php                  |   3 -
 8 files changed, 3 insertions(+), 620 deletions(-)
 delete mode 100644 modules/cdc/config-templates/module_cdc.php
 delete mode 100644 modules/cdc/default-disable
 delete mode 100644 modules/cdc/lib/Auth/Process/CDC.php
 delete mode 100644 modules/cdc/lib/Client.php
 delete mode 100644 modules/cdc/lib/Server.php
 delete mode 100644 modules/cdc/www/resume.php
 delete mode 100644 modules/cdc/www/server.php

diff --git a/bin/build-release.sh b/bin/build-release.sh
index 57d4421d4..344a6380e 100755
--- a/bin/build-release.sh
+++ b/bin/build-release.sh
@@ -44,11 +44,12 @@ fi
 php "$TARGET/composer.phar" install --no-dev --prefer-dist -o -d "$TARGET"
 
 # Install external modules
+php "$TARGET/composer.phar" require --update-no-dev simplesamlphp/simplesamlphp-module-cdc
 php "$TARGET/composer.phar" require --update-no-dev simplesamlphp/simplesamlphp-module-memcookie
-php "$TARGET/composer.phar" require --update-no-dev simplesamlphp/simplesamlphp-module-riak
 php "$TARGET/composer.phar" require --update-no-dev simplesamlphp/simplesamlphp-module-oauth
+php "$TARGET/composer.phar" require --update-no-dev simplesamlphp/simplesamlphp-module-riak
 
-cd $TARGET 
+cd $TARGET
 npm install
 npm audit fix
 npm run build
diff --git a/modules/cdc/config-templates/module_cdc.php b/modules/cdc/config-templates/module_cdc.php
deleted file mode 100644
index 411bbc471..000000000
--- a/modules/cdc/config-templates/module_cdc.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-
-$config = [
-    'example.org' => [
-        /*
-         * The shared key for this CDC server.
-         */
-        'key' => 'ExampleSharedKey',
-
-        /*
-         * The URL to the server script.
-         */
-        'server' => 'https://my-cdc.example.org/simplesaml/module.php/cdc/server.php',
-
-        /*
-         * The lifetime of our cookie, in seconds.
-         *
-         * If this is 0, the cookie will expire when the browser is closed.
-         */
-        'cookie.lifetime' => 0,
-    ],
-];
diff --git a/modules/cdc/default-disable b/modules/cdc/default-disable
deleted file mode 100644
index fa0bd82e2..000000000
--- a/modules/cdc/default-disable
+++ /dev/null
@@ -1,3 +0,0 @@
-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/cdc/lib/Auth/Process/CDC.php b/modules/cdc/lib/Auth/Process/CDC.php
deleted file mode 100644
index bf2a669d6..000000000
--- a/modules/cdc/lib/Auth/Process/CDC.php
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-
-namespace SimpleSAML\module\cdc\Auth\Process;
-
-/**
- * Filter for setting the SAML 2 common domain cookie.
- *
- * @package SimpleSAMLphp
- */
-
-class CDC extends \SimpleSAML\Auth\ProcessingFilter
-{
-    /**
-     * Our CDC domain.
-     *
-     * @var string
-     */
-    private $domain;
-
-
-    /**
-     * Our CDC client.
-     *
-     * @var \SimpleSAML\Module\cdc\Client
-     */
-    private $client;
-
-
-    /**
-     * 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 (!isset($config['domain'])) {
-            throw new \SimpleSAML\Error\Exception('Missing domain option in cdc:CDC filter.');
-        }
-        $this->domain = (string) $config['domain'];
-
-        $this->client = new \SimpleSAML\Module\cdc\Client($this->domain);
-    }
-
-
-    /**
-     * Redirect to page setting CDC.
-     *
-     * @param array &$state  The request state.
-     */
-    public function process(&$state)
-    {
-        assert(is_array($state));
-
-        if (!isset($state['Source']['entityid'])) {
-            \SimpleSAML\Logger::warning('saml:CDC: Could not find IdP entityID.');
-            return;
-        }
-
-        // Save state and build request
-        $id = \SimpleSAML\Auth\State::saveState($state, 'cdc:resume');
-
-        $returnTo = \SimpleSAML\Module::getModuleURL('cdc/resume.php', ['domain' => $this->domain]);
-
-        $params = [
-            'id' => $id,
-            'entityID' => $state['Source']['entityid'],
-        ];
-        $this->client->sendRequest($returnTo, 'append', $params);
-    }
-}
diff --git a/modules/cdc/lib/Client.php b/modules/cdc/lib/Client.php
deleted file mode 100644
index 609aef63f..000000000
--- a/modules/cdc/lib/Client.php
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-
-namespace SimpleSAML\Module\cdc;
-
-/**
- * CDC client class.
- *
- * @package SimpleSAMLphp
- */
-
-class Client
-{
-    /**
-     * Our CDC domain.
-     *
-     * @var string
-     */
-    private $domain;
-
-
-    /**
-     * The CDC server we send requests to.
-     *
-     * @var Server|NULL
-     */
-    private $server;
-
-
-    /**
-     * Initialize a CDC client.
-     *
-     * @param string $domain  The domain we should query the server for.
-     */
-    public function __construct($domain)
-    {
-        assert(is_string($domain));
-
-        $this->domain = $domain;
-        $this->server = new Server($domain);
-    }
-
-
-    /**
-     * Receive a CDC response.
-     *
-     * @return array|NULL  The response, or NULL if no response is received.
-     */
-    public function getResponse()
-    {
-        return $this->server->getResponse();
-    }
-
-
-    /**
-     * Send a request.
-     *
-     * @param string $returnTo  The URL we should return to afterwards.
-     * @param string $op  The operation we are performing.
-     * @param array $params  Additional parameters.
-     */
-    public function sendRequest($returnTo, $op, array $params = [])
-    {
-        assert(is_string($returnTo));
-        assert(is_string($op));
-
-        $params['op'] = $op;
-        $params['return'] = $returnTo;
-        $this->server->sendRequest($params);
-    }
-}
diff --git a/modules/cdc/lib/Server.php b/modules/cdc/lib/Server.php
deleted file mode 100644
index affcf668a..000000000
--- a/modules/cdc/lib/Server.php
+++ /dev/null
@@ -1,426 +0,0 @@
-<?php
-
-namespace SimpleSAML\Module\cdc;
-
-/**
- * CDC server class.
- *
- * @package SimpleSAMLphp
- */
-
-class Server
-{
-    /**
-     * The domain.
-     *
-     * @var string
-     */
-    private $domain;
-
-
-    /**
-     * The URL to the server.
-     *
-     * @var string
-     */
-    private $server;
-
-
-    /**
-     * Our shared key.
-     *
-     * @var string
-     */
-    private $key;
-
-
-    /**
-     * The lifetime of our cookie, in seconds.
-     *
-     * If this is 0, the cookie will expire when the browser is closed.
-     *
-     * @param int
-     */
-    private $cookieLifetime;
-
-
-    /**
-     * Initialize a CDC server.
-     *
-     * @param string $domain  The domain we are a server for.
-     */
-    public function __construct($domain)
-    {
-        assert(is_string($domain));
-
-        $cdcConfig = \SimpleSAML\Configuration::getConfig('module_cdc.php');
-        $config = $cdcConfig->getConfigItem($domain, null);
-
-        if ($config === null) {
-            throw new \SimpleSAML\Error\Exception('Unknown CDC domain: '.var_export($domain, true));
-        }
-
-        $this->domain = $domain;
-        $this->server = $config->getString('server');
-        $this->key = $config->getString('key');
-        $this->cookieLifetime = $config->getInteger('cookie.lifetime', 0);
-
-        if ($this->key === 'ExampleSharedKey') {
-            throw new \SimpleSAML\Error\Exception(
-                'Key for CDC domain '.var_export($domain, true).' not changed from default.'
-            );
-        }
-    }
-
-
-    /**
-     * Send a request to this CDC server.
-     *
-     * @param array $request  The CDC request.
-     */
-    public function sendRequest(array $request)
-    {
-        assert(isset($request['return']));
-        assert(isset($request['op']));
-
-        $request['domain'] = $this->domain;
-        $this->send($this->server, 'CDCRequest', $request);
-    }
-
-
-    /**
-     * Parse and validate response received from a CDC server.
-     *
-     * @return array|NULL  The response, or NULL if no response is received.
-     */
-    public function getResponse()
-    {
-        $response = self::get('CDCResponse');
-        if ($response === null) {
-            return null;
-        }
-
-        if ($response['domain'] !== $this->domain) {
-            throw new \SimpleSAML\Error\Exception('Response received from wrong domain.');
-        }
-
-        $this->validate('CDCResponse');
-
-        return $response;
-    }
-
-
-    /**
-     * Parse and process a CDC request.
-     */
-    public static function processRequest()
-    {
-        $request = self::get('CDCRequest');
-        if ($request === null) {
-            throw new \SimpleSAML\Error\BadRequest('Missing "CDCRequest" parameter.');
-        }
-
-        $domain = $request['domain'];
-        $server = new Server($domain);
-
-        $server->validate('CDCRequest');
-        $server->handleRequest($request);
-    }
-
-
-    /**
-     * Handle a parsed CDC requst.
-     *
-     * @param array $request
-     */
-    private function handleRequest(array $request)
-    {
-        if (!isset($request['op'])) {
-            throw new \SimpleSAML\Error\BadRequest('Missing "op" in CDC request.');
-        }
-        $op = (string) $request['op'];
-
-        \SimpleSAML\Logger::info('Received CDC request with "op": '.var_export($op, true));
-
-        if (!isset($request['return'])) {
-            throw new \SimpleSAML\Error\BadRequest('Missing "return" in CDC request.');
-        }
-        $return = (string) $request['return'];
-
-        switch ($op) {
-            case 'append':
-                $response = $this->handleAppend($request);
-                break;
-            case 'delete':
-                $response = $this->handleDelete($request);
-                break;
-            case 'read':
-                $response = $this->handleRead($request);
-                break;
-            default:
-                $response = 'unknown-op';
-        }
-
-        if (is_string($response)) {
-            $response = [
-                'status' => $response,
-            ];
-        }
-
-        $response['op'] = $op;
-        if (isset($request['id'])) {
-            $response['id'] = (string) $request['id'];
-        }
-        $response['domain'] = $this->domain;
-
-        $this->send($return, 'CDCResponse', $response);
-    }
-
-
-    /**
-     * Handle an append request.
-     *
-     * @param array $request  The request.
-     * @return string The response.
-     */
-    private function handleAppend(array $request)
-    {
-        if (!isset($request['entityID'])) {
-            throw new \SimpleSAML\Error\BadRequest('Missing entityID in append request.');
-        }
-        $entityID = (string) $request['entityID'];
-
-        $list = $this->getCDC();
-
-        $prevIndex = array_search($entityID, $list, true);
-        if ($prevIndex !== false) {
-            unset($list[$prevIndex]);
-        }
-        $list[] = $entityID;
-
-        $this->setCDC($list);
-
-        return 'ok';
-    }
-
-
-    /**
-     * Handle a delete request.
-     *
-     * @param array $request  The request.
-     * @return string The response.
-     */
-    private function handleDelete(array $request)
-    {
-        $params = [
-            'path' => '/',
-            'domain' => '.'.$this->domain,
-            'secure' => true,
-            'httponly' => false,
-        ];
-
-        \SimpleSAML\Utils\HTTP::setCookie('_saml_idp', null, $params, false);
-        return 'ok';
-    }
-
-
-    /**
-     * Handle a read request.
-     *
-     * @param array $request  The request.
-     * @return array  The response.
-     */
-    private function handleRead(array $request)
-    {
-        $list = $this->getCDC();
-
-        return [
-            'status' => 'ok',
-            'cdc' => $list,
-        ];
-    }
-
-
-    /**
-     * Helper function for parsing and validating a CDC message.
-     *
-     * @param string $parameter  The name of the query parameter.
-     * @return array|NULL  The response, or NULL if no response is received.
-     */
-    private static function get($parameter)
-    {
-        assert(is_string($parameter));
-
-        if (!isset($_REQUEST[$parameter])) {
-            return null;
-        }
-        $message = (string) $_REQUEST[$parameter];
-
-        $message = @base64_decode($message);
-        if ($message === false) {
-            throw new \SimpleSAML\Error\BadRequest('Error base64-decoding CDC message.');
-        }
-
-        $message = @json_decode($message, true);
-        if ($message === false) {
-            throw new \SimpleSAML\Error\BadRequest('Error json-decoding CDC message.');
-        }
-
-        if (!isset($message['timestamp'])) {
-            throw new \SimpleSAML\Error\BadRequest('Missing timestamp in CDC message.');
-        }
-        $timestamp = (int) $message['timestamp'];
-
-        if ($timestamp + 60 < time()) {
-            throw new \SimpleSAML\Error\BadRequest('CDC signature has expired.');
-        }
-        if ($timestamp - 60 > time()) {
-            throw new \SimpleSAML\Error\BadRequest('CDC signature from the future.');
-        }
-
-        if (!isset($message['domain'])) {
-            throw new \SimpleSAML\Error\BadRequest('Missing domain in CDC message.');
-        }
-
-        return $message;
-    }
-
-
-    /**
-     * Helper function for validating the signature on a CDC message.
-     *
-     * Will throw an exception if the message is invalid.
-     *
-     * @param string $parameter  The name of the query parameter.
-     */
-    private function validate($parameter)
-    {
-        assert(is_string($parameter));
-        assert(isset($_REQUEST[$parameter]));
-
-        $message = (string) $_REQUEST[$parameter];
-
-        if (!isset($_REQUEST['Signature'])) {
-            throw new \SimpleSAML\Error\BadRequest('Missing Signature on CDC message.');
-        }
-        $signature = (string) $_REQUEST['Signature'];
-
-        $cSignature = $this->calcSignature($message);
-        if ($signature !== $cSignature) {
-            throw new \SimpleSAML\Error\BadRequest('Invalid signature on CDC message.');
-        }
-    }
-
-
-    /**
-     * Helper function for sending CDC messages.
-     *
-     * @param string $to  The URL the message should be delivered to.
-     * @param string $parameter  The query parameter the message should be sent in.
-     * @param array $message  The CDC message.
-     */
-    private function send($to, $parameter, array $message)
-    {
-        assert(is_string($to));
-        assert(is_string($parameter));
-
-        $message['timestamp'] = time();
-        $message = json_encode($message);
-        $message = base64_encode($message);
-
-        $signature = $this->calcSignature($message);
-
-        $params = [
-            $parameter => $message,
-            'Signature' => $signature,
-        ];
-
-        $url = \SimpleSAML\Utils\HTTP::addURLParameters($to, $params);
-        if (strlen($url) < 2048) {
-            \SimpleSAML\Utils\HTTP::redirectTrustedURL($url);
-        } else {
-            \SimpleSAML\Utils\HTTP::submitPOSTData($to, $params);
-        }
-    }
-
-
-    /**
-     * Calculate the signature on the given message.
-     *
-     * @param string $rawMessage  The base64-encoded message.
-     * @return string  The signature.
-     */
-    private function calcSignature($rawMessage)
-    {
-        assert(is_string($rawMessage));
-
-        return sha1($this->key.$rawMessage.$this->key);
-    }
-
-
-    /**
-     * Get the IdP entities saved in the common domain cookie.
-     *
-     * @return array  List of IdP entities.
-     */
-    private function getCDC()
-    {
-        if (!isset($_COOKIE['_saml_idp'])) {
-            return [];
-        }
-
-        $ret = (string) $_COOKIE['_saml_idp'];
-        $ret = explode(' ', $ret);
-        foreach ($ret as &$idp) {
-            $idp = base64_decode($idp);
-            if ($idp === false) {
-                // Not properly base64 encoded
-                \SimpleSAML\Logger::warning('CDC - Invalid base64-encoding of CDC entry.');
-                return [];
-            }
-        }
-
-        return $ret;
-    }
-
-
-    /**
-     * Build a CDC cookie string.
-     *
-     * @param array $list  The list of IdPs.
-     * @return string  The CDC cookie value.
-     */
-    private function setCDC(array $list)
-    {
-        foreach ($list as &$value) {
-            $value = base64_encode($value);
-        }
-
-        $cookie = implode(' ', $list);
-
-        while (strlen($cookie) > 4000) {
-            // The cookie is too long. Remove the oldest elements until it is short enough
-            $tmp = explode(' ', $cookie, 2);
-            if (count($tmp) === 1) {
-                /*
-                 * We are left with a single entityID whose base64
-                 * representation is too long to fit in a cookie.
-                 */
-                break;
-            }
-            $cookie = $tmp[1];
-        }
-
-        $params = [
-            'lifetime' => $this->cookieLifetime,
-            'path' => '/',
-            'domain' => '.'.$this->domain,
-            'secure' => true,
-            'httponly' => false,
-        ];
-
-        \SimpleSAML\Utils\HTTP::setCookie('_saml_idp', $cookie, $params, false);
-
-        return '_saml_idp';
-    }
-}
diff --git a/modules/cdc/www/resume.php b/modules/cdc/www/resume.php
deleted file mode 100644
index ebe6b1cc9..000000000
--- a/modules/cdc/www/resume.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-
-if (!array_key_exists('domain', $_REQUEST)) {
-    throw new \SimpleSAML\Error\BadRequest('Missing domain to CDC resume handler.');
-}
-
-$domain = (string) $_REQUEST['domain'];
-$client = new \SimpleSAML\Module\cdc\Client($domain);
-
-$response = $client->getResponse();
-if ($response === null) {
-    throw new \SimpleSAML\Error\BadRequest('Missing CDC response to CDC resume handler.');
-}
-
-if (!isset($response['id'])) {
-    throw new \SimpleSAML\Error\BadRequest('CDCResponse without id.');
-}
-$state = \SimpleSAML\Auth\State::loadState($response['id'], 'cdc:resume');
-
-\SimpleSAML\Auth\ProcessingChain::resumeProcessing($state);
diff --git a/modules/cdc/www/server.php b/modules/cdc/www/server.php
deleted file mode 100644
index d5cfd16ec..000000000
--- a/modules/cdc/www/server.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<?php
-
-\SimpleSAML\Module\cdc\Server::processRequest();
-- 
GitLab