More updates to stop using dev or alpha or beta versions.
[yaffs-website] / web / modules / contrib / security_review / src / Security.php
diff --git a/web/modules/contrib/security_review/src/Security.php b/web/modules/contrib/security_review/src/Security.php
new file mode 100644 (file)
index 0000000..3104c86
--- /dev/null
@@ -0,0 +1,378 @@
+<?php
+
+namespace Drupal\security_review;
+
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\DependencyInjection\DependencySerializationTrait;
+use Drupal\Core\DrupalKernelInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\user\Entity\Role;
+
+/**
+ * Provides frequently used security-related data.
+ */
+class Security {
+
+  use DependencySerializationTrait;
+
+  /**
+   * The config factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   */
+  protected $configFactory;
+
+  /**
+   * The Drupal kernel.
+   *
+   * @var \Drupal\Core\DrupalKernelInterface
+   */
+  protected $kernel;
+
+  /**
+   * The module handler.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
+   * The security_review service.
+   *
+   * @var \Drupal\security_review\SecurityReview
+   */
+  protected $securityReview;
+
+  /**
+   * Constructs a Security instance.
+   *
+   * @param \Drupal\security_review\SecurityReview $security_review
+   *   The SecurityReview service.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler.
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+   *   The config factory.
+   * @param \Drupal\Core\DrupalKernelInterface $kernel
+   *   The Drupal kernel.
+   */
+  public function __construct(SecurityReview $security_review, ModuleHandlerInterface $module_handler, ConfigFactoryInterface $config_factory, DrupalKernelInterface $kernel) {
+    // Store the dependencies.
+    $this->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;
+  }
+
+}