Commit 18f46fb5 authored by Andrew Nicols's avatar Andrew Nicols Committed by Jenkins
Browse files

MDL-68974 admin: Prevent login as outside of the desired context

parent 2704b00d
......@@ -521,6 +521,16 @@ function has_capability($capability, context $context, $user = null, $doanything
}
}
if (!empty($USER->loginascontext)) {
// The current user is logged in as another user and can assume their identity at or below the `loginascontext`
// defined in the USER session.
// The user may not assume their identity at any other location.
if (!$USER->loginascontext->is_parent_of($context, true)) {
// The context being checked is not the specified context, or one of its children.
return false;
}
}
// Find out if user is admin - it is not possible to override the doanything in any way
// and it is not possible to switch to admin role either.
if ($doanything) {
......@@ -5527,6 +5537,30 @@ abstract class context extends stdClass implements IteratorAggregate {
return $result;
}
/**
* Determine if the current context is a parent of the possible child.
*
* @param context $possiblechild
* @param bool $includeself Whether to check the current context
* @return bool
*/
public function is_parent_of(context $possiblechild, bool $includeself): bool {
// A simple substring check is used on the context path.
// The possible child's path is used as a haystack, with the current context as the needle.
// The path is prefixed with '+' to ensure that the parent always starts at the top.
// It is suffixed with '+' to ensure that parents are not included.
// The needle always suffixes with a '/' to ensure that the contextid uses a complete match (i.e. 142/ instead of 14).
// The haystack is suffixed with '/+' if $includeself is true to allow the current context to match.
// The haystack is suffixed with '+' if $includeself is false to prevent the current context from matching.
$haystacksuffix = $includeself ? '/+' : '+';
$strpos = strpos(
"+{$possiblechild->path}{$haystacksuffix}",
"+{$this->path}/"
);
return $strpos === 0;
}
/**
* Returns parent contexts of this context in reversed order, i.e. parent first,
* then grand parent, etc.
......@@ -5551,6 +5585,30 @@ abstract class context extends stdClass implements IteratorAggregate {
return $result;
}
/**
* Determine if the current context is a child of the possible parent.
*
* @param context $possibleparent
* @param bool $includeself Whether to check the current context
* @return bool
*/
public function is_child_of(context $possibleparent, bool $includeself): bool {
// A simple substring check is used on the context path.
// The current context is used as a haystack, with the possible parent as the needle.
// The path is prefixed with '+' to ensure that the parent always starts at the top.
// It is suffixed with '+' to ensure that children are not included.
// The needle always suffixes with a '/' to ensure that the contextid uses a complete match (i.e. 142/ instead of 14).
// The haystack is suffixed with '/+' if $includeself is true to allow the current context to match.
// The haystack is suffixed with '+' if $includeself is false to prevent the current context from matching.
$haystacksuffix = $includeself ? '/+' : '+';
$strpos = strpos(
"+{$this->path}{$haystacksuffix}",
"+{$possibleparent->path}/"
);
return $strpos === 0;
}
/**
* Returns parent context ids of this context in reversed order, i.e. parent first,
* then grand parent, etc.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment