AppDirsWithDifferentOwner.php 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OCA\Settings\SetupChecks;
  8. use OCP\IL10N;
  9. use OCP\SetupCheck\ISetupCheck;
  10. use OCP\SetupCheck\SetupResult;
  11. class AppDirsWithDifferentOwner implements ISetupCheck {
  12. public function __construct(
  13. private IL10N $l10n,
  14. ) {
  15. }
  16. public function getName(): string {
  17. return $this->l10n->t('App directories owner');
  18. }
  19. public function getCategory(): string {
  20. return 'security';
  21. }
  22. /**
  23. * Iterates through the configured app roots and
  24. * tests if the subdirectories are owned by the same user than the current user.
  25. *
  26. * @return string[]
  27. */
  28. private function getAppDirsWithDifferentOwner(int $currentUser): array {
  29. $appDirsWithDifferentOwner = [[]];
  30. foreach (\OC::$APPSROOTS as $appRoot) {
  31. if ($appRoot['writable'] === true) {
  32. $appDirsWithDifferentOwner[] = $this->getAppDirsWithDifferentOwnerForAppRoot($currentUser, $appRoot);
  33. }
  34. }
  35. $appDirsWithDifferentOwner = array_merge(...$appDirsWithDifferentOwner);
  36. sort($appDirsWithDifferentOwner);
  37. return $appDirsWithDifferentOwner;
  38. }
  39. /**
  40. * Tests if the directories for one apps directory are writable by the current user.
  41. *
  42. * @param int $currentUser The current user
  43. * @param array $appRoot The app root config
  44. * @return string[] The none writable directory paths inside the app root
  45. */
  46. private function getAppDirsWithDifferentOwnerForAppRoot(int $currentUser, array $appRoot): array {
  47. $appDirsWithDifferentOwner = [];
  48. $appsPath = $appRoot['path'];
  49. $appsDir = new \DirectoryIterator($appRoot['path']);
  50. foreach ($appsDir as $fileInfo) {
  51. if ($fileInfo->isDir() && !$fileInfo->isDot()) {
  52. $absAppPath = $appsPath . DIRECTORY_SEPARATOR . $fileInfo->getFilename();
  53. $appDirUser = fileowner($absAppPath);
  54. if ($appDirUser !== $currentUser) {
  55. $appDirsWithDifferentOwner[] = $absAppPath;
  56. }
  57. }
  58. }
  59. return $appDirsWithDifferentOwner;
  60. }
  61. public function run(): SetupResult {
  62. $currentUser = posix_getuid();
  63. $currentUserInfos = posix_getpwuid($currentUser) ?: [];
  64. $appDirsWithDifferentOwner = $this->getAppDirsWithDifferentOwner($currentUser);
  65. if (count($appDirsWithDifferentOwner) > 0) {
  66. return SetupResult::warning(
  67. $this->l10n->t("Some app directories are owned by a different user than the web server one. This may be the case if apps have been installed manually. Check the permissions of the following app directories:\n%s", implode("\n", $appDirsWithDifferentOwner))
  68. );
  69. } else {
  70. return SetupResult::success($this->l10n->t('App directories have the correct owner "%s"', [$currentUserInfos['name'] ?? '']));
  71. }
  72. }
  73. }