* * @author Côme Chilliet * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * */ namespace OCA\Settings\SetupChecks; use OCP\IL10N; use OCP\SetupCheck\ISetupCheck; use OCP\SetupCheck\SetupResult; class AppDirsWithDifferentOwner implements ISetupCheck { public function __construct( private IL10N $l10n, ) { } public function getName(): string { return $this->l10n->t('App directories owner'); } public function getCategory(): string { return 'security'; } /** * Iterates through the configured app roots and * tests if the subdirectories are owned by the same user than the current user. * * @return string[] */ private function getAppDirsWithDifferentOwner(int $currentUser): array { $appDirsWithDifferentOwner = [[]]; foreach (\OC::$APPSROOTS as $appRoot) { if ($appRoot['writable'] === true) { $appDirsWithDifferentOwner[] = $this->getAppDirsWithDifferentOwnerForAppRoot($currentUser, $appRoot); } } $appDirsWithDifferentOwner = array_merge(...$appDirsWithDifferentOwner); sort($appDirsWithDifferentOwner); return $appDirsWithDifferentOwner; } /** * Tests if the directories for one apps directory are writable by the current user. * * @param int $currentUser The current user * @param array $appRoot The app root config * @return string[] The none writable directory paths inside the app root */ private function getAppDirsWithDifferentOwnerForAppRoot(int $currentUser, array $appRoot): array { $appDirsWithDifferentOwner = []; $appsPath = $appRoot['path']; $appsDir = new \DirectoryIterator($appRoot['path']); foreach ($appsDir as $fileInfo) { if ($fileInfo->isDir() && !$fileInfo->isDot()) { $absAppPath = $appsPath . DIRECTORY_SEPARATOR . $fileInfo->getFilename(); $appDirUser = fileowner($absAppPath); if ($appDirUser !== $currentUser) { $appDirsWithDifferentOwner[] = $absAppPath; } } } return $appDirsWithDifferentOwner; } public function run(): SetupResult { $currentUser = posix_getuid(); $currentUserInfos = posix_getpwuid($currentUser) ?: []; $appDirsWithDifferentOwner = $this->getAppDirsWithDifferentOwner($currentUser); if (count($appDirsWithDifferentOwner) > 0) { return SetupResult::warning( $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)) ); } else { return SetupResult::success($this->l10n->t('App directories have the correct owner "%s"', [$currentUserInfos['name'] ?? ''])); } } }