Skip to content

Commit

Permalink
MDL-75753 mod_bigbluebuttonbn: Support SHA256 and SHA512 checksum
Browse files Browse the repository at this point in the history
* Add support for SHA256 and SHA512 checksum
  • Loading branch information
laurentdavid committed Feb 24, 2023
1 parent 9ee4f8d commit 7bd13d5
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 44 deletions.
11 changes: 11 additions & 0 deletions mod/bigbluebuttonbn/classes/local/config.php
Expand Up @@ -39,6 +39,16 @@ class config {
/** @var string Default bigbluebutton data processing agreement url */
public const DEFAULT_DPA_URL = 'https://blindsidenetworks.com/dpa-moodle-free-tier';

/** @var string the default bigbluebutton checksum algorithm */
public const DEFAULT_CHECKSUM_ALGORITHM = 'SHA1';

/** @var array list of supported bigbluebutton checksum algorithm */
const CHECKSUM_ALGORITHMS = [
self::DEFAULT_CHECKSUM_ALGORITHM,
'SHA256',
'SHA512'
];

/**
* Returns moodle version.
*
Expand Down Expand Up @@ -112,6 +122,7 @@ protected static function defaultvalues(): array {
'welcome_default' => '',
'default_dpa_accepted' => false,
'poll_interval' => bigbluebutton_proxy::DEFAULT_POLL_INTERVAL,
'checksum_algorithm' => self::DEFAULT_CHECKSUM_ALGORITHM,
];
}

Expand Down
21 changes: 16 additions & 5 deletions mod/bigbluebuttonbn/classes/local/proxy/proxy_base.php
Expand Up @@ -21,7 +21,6 @@
use mod_bigbluebuttonbn\local\exceptions\server_not_available_exception;
use mod_bigbluebuttonbn\plugin;
use moodle_url;
use SimpleXMLElement;

/**
* The abstract proxy base class.
Expand Down Expand Up @@ -61,15 +60,16 @@ protected static function action_url(string $action = '', array $data = [], arra
}, array_keys($metadata)), $metadata);

$params = http_build_query($data + $metadata, '', '&');
return $baseurl . $params . '&checksum=' . sha1($action . $params . self::sanitized_secret());
$checksum = self::get_checksum($action, $params);
return $baseurl . $params . '&checksum=' . $checksum;
}

/**
* Makes sure the url used doesn't is in the format required.
*
* @return string
*/
protected static function sanitized_url() {
protected static function sanitized_url(): string {
$serverurl = trim(config::get('server_url'));
if (PHPUNIT_TEST) {
$serverurl = (new moodle_url(TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER))->out(false);
Expand All @@ -95,7 +95,7 @@ protected static function sanitized_secret(): string {
/**
* Throw an exception if there is a problem in the returned XML value
*
* @param SimpleXMLElement|bool $xml
* @param \SimpleXMLElement|bool $xml
* @param array|null $additionaldetails
* @throws bigbluebutton_exception
* @throws server_not_available_exception
Expand Down Expand Up @@ -164,7 +164,7 @@ private static function is_known_server_unavailable_errorcode(string $messagekey
* @param string $action
* @param array $data
* @param array $metadata
* @return null|bool|SimpleXMLElement
* @return null|bool|\SimpleXMLElement
*/
protected static function fetch_endpoint_xml(
string $action,
Expand All @@ -179,4 +179,15 @@ protected static function fetch_endpoint_xml(
$curl = new curl();
return $curl->get(self::action_url($action, $data, $metadata));
}

/**
* Get checksum
*
* @param string $action
* @param string $params
* @return string
*/
public static function get_checksum(string $action, string $params): string {
return hash(config::get('checksum_algorithm'), $action . $params . self::sanitized_secret());
}
}
5 changes: 3 additions & 2 deletions mod/bigbluebuttonbn/classes/setting_validator.php
Expand Up @@ -37,7 +37,8 @@ class setting_validator {
public static function section_general_shown() {
global $CFG;
return (!isset($CFG->bigbluebuttonbn['server_url']) ||
!isset($CFG->bigbluebuttonbn['shared_secret'])
!isset($CFG->bigbluebuttonbn['shared_secret']) ||
!isset($CFG->bigbluebuttonbn['checksum_algorithm'])
);
}

Expand All @@ -49,7 +50,7 @@ public static function section_general_shown() {
public static function section_default_messages_shown() {
global $CFG;
return (!isset($CFG->bigbluebuttonbn['welcome_default']) ||
!isset($CFG->bigbluebuttonbn['welcome_editable']));
!isset($CFG->bigbluebuttonbn['welcome_editable']));
}

/**
Expand Down
15 changes: 15 additions & 0 deletions mod/bigbluebuttonbn/classes/settings.php
Expand Up @@ -21,6 +21,7 @@
use admin_setting_configcheckbox;
use admin_setting_configmultiselect;
use admin_setting_configpasswordunmask;
use admin_setting_configselect;
use admin_setting_configstoredfile;
use admin_setting_configtext;
use admin_setting_configtextarea;
Expand Down Expand Up @@ -179,6 +180,20 @@ function() {
$item,
$settingsgeneral
);

$item = new admin_setting_configselect(
'bigbluebuttonbn_checksum_algorithm',
get_string('config_checksum_algorithm', 'bigbluebuttonbn'),
get_string('config_checksum_algorithm_description', 'bigbluebuttonbn'),
config::DEFAULT_CHECKSUM_ALGORITHM,
array_combine(config::CHECKSUM_ALGORITHMS, config::CHECKSUM_ALGORITHMS)
);
$this->add_conditional_element(
'checksum_algorithm',
$item,
$settingsgeneral
);

$item = new \admin_setting_description(
'bigbluebuttonbn_dpa_info',
'',
Expand Down
3 changes: 3 additions & 0 deletions mod/bigbluebuttonbn/lang/en/bigbluebuttonbn.php
Expand Up @@ -146,6 +146,9 @@
</ol>';
$string['config_shared_secret'] = 'BigBlueButton shared secret';
$string['config_shared_secret_description'] = 'The security secret of your BigBlueButton server. The default secret is for a free BigBlueButton service provided by Blindside Networks.';
$string['config_checksum_algorithm'] = 'BigBlueButton Checksum Algorithm';
$string['config_checksum_algorithm_description'] = 'The checksum algorithm of your BigBlueButton server.
(SHA1 guarantees compatibility with older server versions but is less secure whereas SHA512 is FIPS 140-2 compliant.)';

$string['config_recording'] = 'Recording';
$string['config_recording_description'] = 'These settings are feature specific';
Expand Down
88 changes: 51 additions & 37 deletions mod/bigbluebuttonbn/tests/generator/lib.php
Expand Up @@ -273,6 +273,50 @@ protected function create_mockserver_recording(instance $instance, stdClass $rec
return (string) $result->recordID;
}

/**
* Utility to send a request to the mock server
*
* @param string $endpoint
* @param array $params
* @param array $mockdata
* @return SimpleXMLElement|bool
* @throws moodle_exception
*/
protected function send_mock_request(string $endpoint, array $params = [], array $mockdata = []): SimpleXMLElement {
$url = $this->get_mocked_server_url($endpoint, $params);

foreach ($mockdata as $key => $value) {
if (is_array($value)) {
foreach ($value as $subkey => $subvalue) {
$paramname = "{$key}_{$subkey}";
$url->param($paramname, $subvalue);
}
} else {
$url->param($key, $value);
}
}

$curl = new \curl();
$result = $curl->get($url->out_omit_querystring(), $url->params());

$retvalue = @simplexml_load_string($result, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
if ($retvalue === false) {
throw new moodle_exception('mockserverconnfailed', 'mod_bigbluebutton');
}
return $retvalue;
}

/**
* Get a URL for a mocked BBB server endpoint.
*
* @param string $endpoint
* @param array $params
* @return moodle_url
*/
protected function get_mocked_server_url(string $endpoint = '', array $params = []): moodle_url {
return new moodle_url(TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER . '/' . $endpoint, $params);
}

/**
* Mock an in-progress meeting on the remote server.
*
Expand Down Expand Up @@ -356,47 +400,17 @@ public static function log_test_event(instance $instance, array $record): void {
}

/**
* Get a URL for a mocked BBB server endpoint.
* Set a value in the Mock server
*
* @param string $endpoint
* @param array $params
* @return moodle_url
*/
protected function get_mocked_server_url(string $endpoint = '', array $params = []): moodle_url {
return new moodle_url(TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER . '/' . $endpoint, $params);
}

/**
* Utility to send a request to the mock server
*
* @param string $endpoint
* @param array $params
* @param array $mockdata
* @return SimpleXMLElement|bool
* @param string $name
* @param mixed $value
* @return void
* @throws moodle_exception
*/
protected function send_mock_request(string $endpoint, array $params = [], array $mockdata = []): SimpleXMLElement {
$url = $this->get_mocked_server_url($endpoint, $params);

foreach ($mockdata as $key => $value) {
if (is_array($value)) {
foreach ($value as $subkey => $subvalue) {
$paramname = "{$key}_{$subkey}";
$url->param($paramname, $subvalue);
}
} else {
$url->param($key, $value);
}
}

$curl = new \curl();
$result = $curl->get($url->out_omit_querystring(), $url->params());

$retvalue = @simplexml_load_string($result, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
if ($retvalue === false) {
throw new moodle_exception('mockserverconnfailed', 'mod_bigbluebutton');
public function set_value(string $name, $value): void {
if (defined('TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER')) {
$this->send_mock_request('backoffice/set', [], ['name' => $name, 'value' => json_encode($value)]);
}
return $retvalue;
}

/**
Expand Down
92 changes: 92 additions & 0 deletions mod/bigbluebuttonbn/tests/local/proxy/proxy_base_test.php
@@ -0,0 +1,92 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle 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 3 of the License, or
// (at your option) any later version.
//
// Moodle 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 Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* Tests for BigBlueButton Proxy server (and checksum).
*
* @package mod_bigbluebuttonbn
* @copyright 2018 - present, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David (laurent [at] call-learning [dt] fr)
*/

namespace mod_bigbluebuttonbn\local\proxy;
use mod_bigbluebuttonbn\test\testcase_helper_trait;

/**
* Proxy base test
*
* @package mod_bigbluebuttonbn
* @copyright 2018 - present, Blindside Networks Inc
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Laurent David (laurent [at] call-learning [dt] fr)
* @covers \mod_bigbluebuttonbn\local\proxy\proxy_base
* @coversDefaultClass \mod_bigbluebuttonbn\local\proxy\proxy_base
*/
class proxy_base_test extends \advanced_testcase {
use testcase_helper_trait;

/**
* Setup
*/
public function setUp(): void {
parent::setUp();
$this->initialise_mock_server();
}

/**
* Test that different checksum algorithm work
*
* @return void
*/
public function test_get_checksum() {
$this->resetAfterTest();
foreach (['SHA1', 'SHA512', 'SHA256'] as $algo) {
set_config('bigbluebuttonbn_checksum_algorithm', $algo);
$xmlinfo = self::get_status();
$this->assertNotEmpty($xmlinfo);
$this->assertEquals('SUCCESS', $xmlinfo->returncode);
}
}

/**
* Test that we send a checksumError whenever the algorithm is not supported
*
* @return void
*/
public function test_get_checksum_not_supported() {
$this->resetAfterTest();
$bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn');
$bbbgenerator->set_value('checksum_algorithms', ['SHA1', 'SHA256']);
// This should not be supported.
set_config('bigbluebuttonbn_checksum_algorithm', 'SHA512');
$xmlinfo = self::get_status();
$this->assertEquals($xmlinfo->messageKey, 'checksumError');
}


/**
* Get the endpoint XML result.
*
* @return mixed
*/
protected static function get_status() {
$rc = new \ReflectionClass(proxy_base::class);
$rcm = $rc->getMethod('fetch_endpoint_xml');
$rcm->setAccessible(true);
return $rcm->invoke(null, '');
}
}

0 comments on commit 7bd13d5

Please sign in to comment.