X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs-website;a=blobdiff_plain;f=web%2Fmodules%2Fcontrib%2Fsecurity_review%2Fsrc%2FSecurity.php;fp=web%2Fmodules%2Fcontrib%2Fsecurity_review%2Fsrc%2FSecurity.php;h=bf280f31aace2add4a091cf6fa1039a7b4e0a509;hp=0000000000000000000000000000000000000000;hb=ba1b5c55c66590c41ccc9844d3e62391b0399abb;hpb=93ef30d42f68e55d11d97312531118bbcd4cf318 diff --git a/web/modules/contrib/security_review/src/Security.php b/web/modules/contrib/security_review/src/Security.php new file mode 100644 index 000000000..bf280f31a --- /dev/null +++ b/web/modules/contrib/security_review/src/Security.php @@ -0,0 +1,383 @@ +securityReview = $security_review; + $this->moduleHandler = $module_handler; + $this->configFactory = $config_factory; + $this->kernel = $kernel; + } + + /** + * Returns the IDs of untrusted roles. + * + * If the module hasn't been configured yet, it returns the default untrusted + * roles. + * + * @return string[] + * Untrusted roles' IDs. + */ + public function untrustedRoles() { + // If the module hasn't been manually configured yet, return the untrusted + // roles depending on Drupal's actual configuration. + if (!$this->securityReview->isConfigured()) { + return static::defaultUntrustedRoles(); + } + + // Else return the stored untrusted roles. + return $this->securityReview->getUntrustedRoles(); + } + + /** + * Returns the default untrusted roles. + * + * The default untrusted roles are: + * Anonymous : always + * Authenticated : if visitors are allowed to create accounts. + * + * @return string[] + * Default untrusted roles' IDs. + */ + public function defaultUntrustedRoles() { + // Add the Anonymous role to the output array. + $roles = [AccountInterface::ANONYMOUS_ROLE]; + + // Check whether visitors can create accounts. + $user_register = $this->configFactory->get('user.settings') + ->get('register'); + if ($user_register !== USER_REGISTER_ADMINISTRATORS_ONLY) { + // If visitors are allowed to create accounts they are considered + // untrusted. + $roles[] = AccountInterface::AUTHENTICATED_ROLE; + } + + // Return the untrusted roles. + return $roles; + } + + /** + * Returns the permission strings that a group of roles have. + * + * @param string[] $role_ids + * The array of roleIDs to check. + * @param bool $group_by_role_id + * Choose whether to group permissions by role ID. + * + * @return array + * An array of the permissions untrusted roles have. If $groupByRoleId is + * true, the array key is the role ID, the value is the array of permissions + * the role has. + */ + public function rolePermissions(array $role_ids, $group_by_role_id = FALSE) { + // Get the permissions the given roles have, grouped by roles. + $permissions_grouped = user_role_permissions($role_ids); + + // Fill up the administrative roles' permissions too. + foreach ($role_ids as $role_id) { + $role = Role::load($role_id); + /** @var Role $role */ + if ($role->isAdmin()) { + $permissions_grouped[$role_id] = $this->permissions(); + } + } + + if ($group_by_role_id) { + // If the result should be grouped, we have nothing else to do. + return $permissions_grouped; + } + else { + // Merge the grouped permissions into $untrusted_permissions. + $untrusted_permissions = []; + foreach ($permissions_grouped as $permissions) { + $untrusted_permissions = array_merge($untrusted_permissions, $permissions); + } + + // Remove duplicate elements and fix indexes. + $untrusted_permissions = array_values(array_unique($untrusted_permissions)); + return $untrusted_permissions; + } + } + + /** + * Returns the permission strings that untrusted roles have. + * + * @param bool $group_by_role_id + * Choose whether to group permissions by role ID. + * + * @return array + * An array of the permissions untrusted roles have. If $groupByRoleId is + * true, the array key is the role ID, the value is the array of permissions + * the role has. + */ + public function untrustedPermissions($group_by_role_id = FALSE) { + return $this->rolePermissions($this->untrustedRoles(), $group_by_role_id); + } + + /** + * Returns the trusted roles. + * + * @return array + * Trusted roles' IDs. + */ + public function trustedRoles() { + // Get the stored/default untrusted roles. + $untrusted_roles = $this->untrustedRoles(); + + // Iterate through all the roles, and store which are not untrusted. + $trusted = []; + foreach (user_roles() as $role) { + if (!in_array($role->id(), $untrusted_roles)) { + $trusted[] = $role->id(); + } + } + + // Return the trusted roles. + return $trusted; + } + + /** + * Returns the permission strings that trusted roles have. + * + * @param bool $group_by_role_id + * Choose whether to group permissions by role ID. + * + * @return array + * An array of the permissions trusted roles have. If $groupByRoleId is + * true, the array key is the role ID, the value is the array of permissions + * the role has. + */ + public function trustedPermissions($group_by_role_id = FALSE) { + return $this->rolePermissions($this->trustedRoles(), $group_by_role_id); + } + + + /** + * Gets all the permissions. + * + * @param bool $meta + * Whether to return only permission strings or metadata too. + * + * @see \Drupal\user\PermissionHandlerInterface::getPermissions() + * + * @return array + * Array of every permission. + */ + public function permissions($meta = FALSE) { + // Not injected because of hard testability. + $permissions = \Drupal::service('user.permissions')->getPermissions(); + + if (!$meta) { + return array_keys($permissions); + } + return $permissions; + } + + /** + * Gets the list of unsafe HTML tags. + * + * @return string[] + * List of unsafe tags. + */ + public function unsafeTags() { + $unsafe_tags = [ + 'applet', + 'area', + 'audio', + 'base', + 'basefont', + 'body', + 'button', + 'comment', + 'embed', + 'eval', + 'form', + 'frame', + 'frameset', + 'head', + 'html', + 'iframe', + 'image', + 'img', + 'input', + 'isindex', + 'label', + 'link', + 'map', + 'math', + 'meta', + 'noframes', + 'noscript', + 'object', + 'optgroup', + 'option', + 'param', + 'script', + 'select', + 'style', + 'svg', + 'table', + 'td', + 'textarea', + 'title', + 'video', + 'vmlframe', + ]; + + // Alter data. + $this->moduleHandler->alter('security_review_unsafe_tags', $unsafe_tags); + + return $unsafe_tags; + } + + /** + * Gets the list of unsafe file extensions. + * + * @return string[] + * List of unsafe extensions. + */ + public function unsafeExtensions() { + $unsafe_ext = [ + 'swf', + 'exe', + 'html', + 'htm', + 'php', + 'phtml', + 'py', + 'js', + 'vb', + 'vbe', + 'vbs', + ]; + + // Alter data. + $this->moduleHandler + ->alter('security_review_unsafe_extensions', $unsafe_ext); + + return $unsafe_ext; + } + + /** + * Returns the site path. + * + * @return string + * Absolute site path. + */ + public function sitePath() { + return DRUPAL_ROOT . '/' . $this->kernel->getSitePath(); + } + + /** + * Finds files and directories that are writable by the web server. + * + * @param string[] $files + * The files to iterate through. + * @param bool $cli + * Whether it is being invoked in CLI context. + * + * @return string[] + * The files that are writable. + */ + public function findWritableFiles(array $files, $cli = FALSE) { + $writable = []; + if (!$cli) { + // Running from UI. + foreach ($files as $file) { + if (is_writable($file)) { + $writable[] = $file; + } + } + } + else { + // Get the web server's user data. + $uid = $this->securityReview->getServerUid(); + $gids = $this->securityReview->getServerGids(); + + foreach ($files as $file) { + $perms = 0777 & fileperms($file); + // Check write permissions for others. + $ow = ($perms >> 1) & 1; + if ($ow === 1) { + $writable[] = $file; + continue; + } + + // Check write permissions for owner. + $uw = ($perms >> 7) & 1; + if ($uw === 1 && fileowner($file) == $uid) { + $writable[] = $file; + continue; + } + + // Check write permissions for group. + $gw = ($perms >> 4) & 1; + if ($gw === 1 && in_array(filegroup($file), $gids)) { + $writable[] = $file; + } + } + } + return $writable; + } + +}