Merge branch 'MDL-75753-master' of https://github.com/call-learning/moodle

This commit is contained in:
Andrew Nicols 2023-03-02 09:14:06 +08:00
commit 0fd0dff885
7 changed files with 191 additions and 44 deletions

View File

@ -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.
*
@ -112,6 +122,7 @@ class config {
'welcome_default' => '',
'default_dpa_accepted' => false,
'poll_interval' => bigbluebutton_proxy::DEFAULT_POLL_INTERVAL,
'checksum_algorithm' => self::DEFAULT_CHECKSUM_ALGORITHM,
];
}

View File

@ -21,7 +21,6 @@ use mod_bigbluebuttonbn\local\exceptions\bigbluebutton_exception;
use mod_bigbluebuttonbn\local\exceptions\server_not_available_exception;
use mod_bigbluebuttonbn\plugin;
use moodle_url;
use SimpleXMLElement;
/**
* The abstract proxy base class.
@ -61,7 +60,8 @@ abstract class proxy_base {
}, 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;
}
/**
@ -69,7 +69,7 @@ abstract class proxy_base {
*
* @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);
@ -95,7 +95,7 @@ abstract class proxy_base {
/**
* 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
@ -164,7 +164,7 @@ abstract class proxy_base {
* @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,
@ -179,4 +179,15 @@ abstract class proxy_base {
$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());
}
}

View File

@ -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'])
);
}
@ -49,7 +50,7 @@ class setting_validator {
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']));
}
/**

View File

@ -21,6 +21,7 @@ use admin_setting;
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;
@ -190,6 +191,20 @@ class settings {
$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',
'',

View File

@ -147,6 +147,9 @@ $string['config_server_url_description'] = 'The default credentials are for a <a
</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';

View File

@ -274,6 +274,50 @@ class mod_bigbluebuttonbn_generator extends \testing_module_generator {
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.
*
@ -357,47 +401,17 @@ class mod_bigbluebuttonbn_generator extends \testing_module_generator {
}
/**
* 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);
}
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)]);
}
$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;
}
/**

View File

@ -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, '');
}
}