mirror of
https://github.com/moodle/moodle.git
synced 2025-04-20 16:04:25 +02:00
Merge branch '79121-normalize-proxy-bypass-404' of https://github.com/DSI-Universite-Rennes2/moodle into MOODLE_404_STABLE
This commit is contained in:
commit
00adbc39f1
@ -181,8 +181,16 @@ if ($hassiteconfig) {
|
||||
new lang_string('configproxyuser', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configpasswordunmask('proxypassword', new lang_string('proxypassword', 'admin'),
|
||||
new lang_string('configproxypassword', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configtext('proxybypass', new lang_string('proxybypass', 'admin'),
|
||||
new lang_string('configproxybypass', 'admin'), 'localhost, 127.0.0.1'));
|
||||
|
||||
$setting = new admin_setting_configtext('proxybypass', new lang_string('proxybypass', 'admin'),
|
||||
new lang_string('configproxybypass', 'admin'), 'localhost,127.0.0.1');
|
||||
$setting->set_updatedcallback(function() {
|
||||
// Normalize $CFG->proxybypass value.
|
||||
$normalizedvalue = \core\ip_utils::normalize_internet_address_list(get_config('core', 'proxybypass'));
|
||||
set_config('proxybypass', $normalizedvalue);
|
||||
});
|
||||
$temp->add($setting);
|
||||
|
||||
$temp->add(new admin_setting_configcheckbox('proxylogunsafe', new lang_string('proxylogunsafe', 'admin'),
|
||||
new lang_string('configproxylogunsafe_help', 'admin'), 0));
|
||||
$temp->add(new admin_setting_configcheckbox('proxyfixunsafe', new lang_string('proxyfixunsafe', 'admin'),
|
||||
|
@ -341,7 +341,7 @@ $string['configperfdebug'] = 'If you turn this on, performance info will be prin
|
||||
$string['configprofileroles'] = 'Roles that are listed in user profiles and on the participants page.';
|
||||
$string['configprofilesforenrolledusersonly'] = 'To prevent misuse by spammers, profile descriptions of users who are not yet enrolled in any course are hidden. New users must enrol in at least one course before they can add a profile description.';
|
||||
$string['configprotectusernames'] = 'If enabled, the forgotten password form will not display any hints allowing account usernames or email addresses to be guessed.';
|
||||
$string['configproxybypass'] = 'Comma separated list of (partial) hostnames or IPs that should bypass proxy (e.g., 192.168., .mydomain.com)';
|
||||
$string['configproxybypass'] = 'List of (partial) hostnames or IP addresses that should bypass the proxy. Separate each item by commas, with no spaces. For example: 192.168.0.0/16,*.mydomain.com.';
|
||||
$string['configproxyhost'] = 'If this <b>server</b> needs to use a proxy computer (eg a firewall) to access the Internet, then provide the proxy hostname here. Otherwise leave it blank.';
|
||||
$string['configproxypassword'] = 'Password needed to access internet through proxy if required, empty if none (PHP cURL extension required).';
|
||||
$string['configproxyport'] = 'If this server needs to use a proxy computer, then provide the proxy port here.';
|
||||
|
@ -263,4 +263,94 @@ final class ip_utils {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize internet address.
|
||||
*
|
||||
* Accepted input formats are :
|
||||
* - a valid range or full ip address (e.g.: 192.168.0.0/16, fe80::ffff, 127.0.0.1 or fe80:fe80:fe80:fe80:fe80:fe80:fe80:fe80)
|
||||
* - a valid domain name or pattern (e.g.: www.moodle.com or *.moodle.org)
|
||||
*
|
||||
* Convert forbidden syntaxes since MDL-74289 to allowed values. For examples:
|
||||
* - 192.168. => 192.168.0.0/16
|
||||
* - .domain.tld => *.domain.tld
|
||||
*
|
||||
* @param string $address The input string to normalize.
|
||||
*
|
||||
* @return string If $address is not normalizable, an empty string is returned.
|
||||
*/
|
||||
public static function normalize_internet_address(string $address): string {
|
||||
$address = str_replace([" ", "\n", "\r", "\t", "\v", "\x00"], '', strtolower($address));
|
||||
|
||||
// Replace previous allowed "192.168." format to CIDR format (192.168.0.0/16).
|
||||
if (str_ends_with($address, '.') && preg_match('/^[0-9\.]+$/', $address) === 1) {
|
||||
$count = substr_count($address, '.');
|
||||
|
||||
// Remove final dot.
|
||||
$address = substr($address, 0, -1);
|
||||
|
||||
// Fill address with missing ".0".
|
||||
$address .= str_repeat('.0', 4 - $count);
|
||||
|
||||
// Add subnet mask.
|
||||
$address .= '/' . ($count * 8);
|
||||
}
|
||||
|
||||
if (self::is_ip_address($address) ||
|
||||
self::is_ipv4_range($address) || self::is_ipv6_range($address)) {
|
||||
|
||||
// Keep full or range ip addresses.
|
||||
return $address;
|
||||
}
|
||||
|
||||
// Replace previous allowed ".domain.tld" format to "*.domain.tld" format.
|
||||
if (str_starts_with($address, '.')) {
|
||||
$address = '*'.$address;
|
||||
}
|
||||
|
||||
// Usually the trailing dot (null label) is omitted, but is valid if supplied. We'll just remove it and validate as normal.
|
||||
$address = rtrim($address, '.');
|
||||
|
||||
if (self::is_domain_name($address) || self::is_domain_matching_pattern($address)) {
|
||||
// Keep valid or pattern domain name.
|
||||
return $address;
|
||||
}
|
||||
|
||||
// Return empty string for invalid values.
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a list of internet addresses.
|
||||
*
|
||||
* This function will:
|
||||
* - normalize internet addresses {@see normalize_internet_address()}
|
||||
* - remove invalid values
|
||||
* - remove duplicate values
|
||||
*
|
||||
* @param string $addresslist A string representing a list of internet addresses separated by a common value.
|
||||
* @param string $separator A separator character used within the list string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function normalize_internet_address_list(string $addresslist, string $separator = ','): string {
|
||||
$addresses = [];
|
||||
foreach (explode($separator, $addresslist) as $value) {
|
||||
$address = self::normalize_internet_address($value);
|
||||
|
||||
if (empty($address)) {
|
||||
// Ignore invalid input.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($address, $addresses, true)) {
|
||||
// Ignore duplicate value.
|
||||
continue;
|
||||
}
|
||||
|
||||
$addresses[] = $address;
|
||||
}
|
||||
|
||||
return implode($separator, $addresses);
|
||||
}
|
||||
}
|
||||
|
@ -400,4 +400,155 @@ final class ip_utils_test extends \basic_testcase {
|
||||
$this->assertEquals($expected, \core\ip_utils::is_ip_in_subnet_list($ip, $list, $delim));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for test_normalize_internet_address.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function normalize_internet_address_provider(): array {
|
||||
return [
|
||||
'Strip all white spaces on IP address' => [
|
||||
' 192.168.5.5 ',
|
||||
'192.168.5.5',
|
||||
],
|
||||
'Strip all white spaces on domain name' => [
|
||||
' www.moodle.org ',
|
||||
'www.moodle.org',
|
||||
],
|
||||
'Preserve IPv4 address' => [
|
||||
'127.0.0.1',
|
||||
'127.0.0.1',
|
||||
],
|
||||
'Preserve IPv4 address range' => [
|
||||
'192.168.0.0/16',
|
||||
'192.168.0.0/16',
|
||||
],
|
||||
'Preserve IPv6 address' => [
|
||||
'fe80:fe80:fe80:fe80:fe80:fe80:fe80:fe80',
|
||||
'fe80:fe80:fe80:fe80:fe80:fe80:fe80:fe80',
|
||||
],
|
||||
'Preserve IPv6 address range' => [
|
||||
'fe80::ffff',
|
||||
'fe80::ffff',
|
||||
],
|
||||
'Preserve valid domain' => [
|
||||
'localhost',
|
||||
'localhost',
|
||||
],
|
||||
'Preserve valid FQDN' => [
|
||||
'www.moodle.org',
|
||||
'www.moodle.org',
|
||||
],
|
||||
'Preserve valid FQDN with trailing dot' => [
|
||||
'www.moodle.com.',
|
||||
'www.moodle.com',
|
||||
],
|
||||
'Preserve valid domain with wildcard' => [
|
||||
'*.moodledev.io',
|
||||
'*.moodledev.io',
|
||||
],
|
||||
'Convert previous allowed "127." format to CIDR format (127.0.0.0/8)' => [
|
||||
'127.',
|
||||
'127.0.0.0/8',
|
||||
],
|
||||
'Convert previous allowed "169.8." format to CIDR format (169.8.0.0/16)' => [
|
||||
'169.8.',
|
||||
'169.8.0.0/16',
|
||||
],
|
||||
'Convert previous allowed "192.168.10." format to CIDR format (192.168.10.0/24)' => [
|
||||
'192.168.10.',
|
||||
'192.168.10.0/24',
|
||||
],
|
||||
'Convert previous allowed ".moodle.org" subdomain format to new format (*.moodle.org)' => [
|
||||
'.moodle.org',
|
||||
'*.moodle.org',
|
||||
],
|
||||
'Ignore invalid IPv4' => [
|
||||
'327.0.0.1',
|
||||
'',
|
||||
],
|
||||
'Ignore invalid IPv4 range' => [
|
||||
'192.168',
|
||||
'',
|
||||
],
|
||||
'Ignore invalid IPv6' => [
|
||||
'fe80::ddddd',
|
||||
'',
|
||||
],
|
||||
'Ignore invalid IPv6 range' => [
|
||||
'fe80:',
|
||||
'',
|
||||
],
|
||||
'Ignore invalid domain' => [
|
||||
'-example.com',
|
||||
'',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if input address value is correctly normalized.
|
||||
*
|
||||
* @covers ::normalize_internet_address
|
||||
*
|
||||
* @dataProvider normalize_internet_address_provider
|
||||
*
|
||||
* @param string $input Raw input value.
|
||||
* @param string $expected Expected value after normalization.
|
||||
*/
|
||||
public function test_normalize_internet_address(string $input, string $expected): void {
|
||||
$this->assertEquals($expected, \core\ip_utils::normalize_internet_address($input));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for test_normalize_internet_address_list.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function normalize_internet_address_list_provider(): array {
|
||||
return [
|
||||
'Strip all white spaces' => [
|
||||
' 192.168.5.5, 127.0.0.1, www.moodle.org ',
|
||||
'192.168.5.5,127.0.0.1,www.moodle.org',
|
||||
],
|
||||
'Trim input' => [
|
||||
' 192.168.5.5,127.0.0.1,www.moodle.org ',
|
||||
'192.168.5.5,127.0.0.1,www.moodle.org',
|
||||
],
|
||||
'Preserve valid full and partial IP' => [
|
||||
'127.0.0.1,192.168.0.0/16,fe80:fe80:fe80:fe80:fe80:fe80:fe80:fe80,fe80::ffff',
|
||||
'127.0.0.1,192.168.0.0/16,fe80:fe80:fe80:fe80:fe80:fe80:fe80:fe80,fe80::ffff',
|
||||
],
|
||||
'Convert previous allowed format to new allowed format' => [
|
||||
'127.,169.8.,192.168.10.,.moodle.org',
|
||||
'127.0.0.0/8,169.8.0.0/16,192.168.10.0/24,*.moodle.org',
|
||||
],
|
||||
'Preserve valid domain and pattern domain' => [
|
||||
'localhost,www.moodle.org,.moodle.com,*.moodledev.io',
|
||||
'localhost,www.moodle.org,*.moodle.com,*.moodledev.io',
|
||||
],
|
||||
'Remove all invalid IP and domains' => [
|
||||
'327.0.0.1,192.168,fe80::ddddd,fe80:,-example.com',
|
||||
'',
|
||||
],
|
||||
'Remove duplicate values' => [
|
||||
'.moodle.org,*.moodle.org,*.moodle.org,.moodle.org',
|
||||
'*.moodle.org',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if input address list is correctly normalized.
|
||||
*
|
||||
* @covers ::normalize_internet_address_list
|
||||
*
|
||||
* @dataProvider normalize_internet_address_list_provider
|
||||
*
|
||||
* @param string $input Raw input value.
|
||||
* @param string $expected Expected value after normalization.
|
||||
*/
|
||||
public function test_normalize_internet_address_list(string $input, string $expected): void {
|
||||
$this->assertEquals($expected, \core\ip_utils::normalize_internet_address_list($input));
|
||||
}
|
||||
}
|
||||
|
@ -5418,38 +5418,83 @@ EOT;
|
||||
return [
|
||||
'Proxybypass contains the same IP as the beginning of the URL' => [
|
||||
'http://192.168.5.5-fake-app-7f000101.nip.io',
|
||||
'192.168.5.5, 127.0.0.1',
|
||||
false
|
||||
'192.168.5.5,127.0.0.1',
|
||||
false,
|
||||
],
|
||||
'Proxybypass contains some extra whitespaces (test with hostname)' => [
|
||||
'store.mydomain.com',
|
||||
'store.mydomain.com , 192.168.5.5',
|
||||
false,
|
||||
],
|
||||
'Proxybypass contains some extra whitespaces (test with IP)' => [
|
||||
'192.168.5.5',
|
||||
'store.mydomain.com , 192.168.5.5',
|
||||
false,
|
||||
],
|
||||
'Proxybypass contains the last part of the URL' => [
|
||||
'http://192.168.5.5-fake-app-7f000101.nip.io',
|
||||
'app-7f000101.nip.io',
|
||||
false
|
||||
false,
|
||||
],
|
||||
'Proxybypass contains the last part of the URL 2' => [
|
||||
'http://store.mydomain.com',
|
||||
'mydomain.com',
|
||||
false
|
||||
false,
|
||||
],
|
||||
'Proxybypass contains part of the url' => [
|
||||
'http://myweb.com',
|
||||
'store.myweb.com',
|
||||
false
|
||||
false,
|
||||
],
|
||||
'Proxybypass with a wildcard contains part of the url' => [
|
||||
'http://myweb.com',
|
||||
'*.myweb.com',
|
||||
false,
|
||||
],
|
||||
'Different IPs used in proxybypass' => [
|
||||
'http://192.168.5.5',
|
||||
'192.168.5.3',
|
||||
false
|
||||
false,
|
||||
],
|
||||
'Different partial IPs used in proxybypass' => [
|
||||
'http://192.168.5.5',
|
||||
'192.16',
|
||||
false,
|
||||
],
|
||||
'Different partial IPs used in proxybypass with ending dot' => [
|
||||
'http://192.168.5.5',
|
||||
'192.16.',
|
||||
false,
|
||||
],
|
||||
'Proxybypass and URL matchs' => [
|
||||
'http://store.mydomain.com',
|
||||
'store.mydomain.com',
|
||||
true
|
||||
true,
|
||||
],
|
||||
'Proxybypass with a wildcard value covers any subdomain' => [
|
||||
'http://store.mydomain.com',
|
||||
'*.mydomain.com',
|
||||
true,
|
||||
],
|
||||
'Proxybypass with a wildcard value covers any higher level subdomain' => [
|
||||
'http://another.store.mydomain.com',
|
||||
'*.mydomain.com',
|
||||
true,
|
||||
],
|
||||
'Proxybypass with multiple domains' => [
|
||||
'http://store.mydomain.com',
|
||||
'127.0.0.1,*.mydomain.com',
|
||||
true,
|
||||
],
|
||||
'IP used in proxybypass' => [
|
||||
'http://192.168.5.5',
|
||||
'192.168.5.5',
|
||||
true
|
||||
true,
|
||||
],
|
||||
'Partial IP used in proxybypass' => [
|
||||
'http://192.168.5.5',
|
||||
'192.168.',
|
||||
true,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
@ -1,6 +1,22 @@
|
||||
This files describes API changes in core libraries and APIs,
|
||||
information provided here is intended especially for developers.
|
||||
|
||||
=== 4.4.6 ===
|
||||
|
||||
* A new core\ip_utils::normalize_internet_address() method is created to
|
||||
sanitize an IP address, a range of IP addresses, a domain name or a
|
||||
wildcard domain matching pattern.
|
||||
|
||||
Moodle previously allowed entries such as 192.168. or .moodle.org for
|
||||
certain variables (eg: $CFG->proxybypass). Since MDL-74289, these
|
||||
formats are no longer allowed. This method converts this informations
|
||||
into an authorized format. For example, 192.168. becomes 192.168.0.0/16
|
||||
and .moodle.org becomes *.moodle.org.
|
||||
|
||||
Also a new core\ip_utils::normalize_internet_address_list() method is
|
||||
created. Based on core\ip_utils::normalize_internet_address(), this
|
||||
method normalizes a string containing a series of Internet addresses.
|
||||
|
||||
=== 4.4.5 ===
|
||||
|
||||
* All uses of the following PHPUnit methods have been removed as these methods are deprecated upstream without direct replacement:
|
||||
|
Loading…
x
Reference in New Issue
Block a user