Skip to content

Commit

Permalink
fixup
Browse files Browse the repository at this point in the history
  • Loading branch information
susnux committed Aug 26, 2024
1 parent 031bfe4 commit 46303c8
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 9 deletions.
2 changes: 1 addition & 1 deletion apps/dav/lib/Connector/Sabre/Directory.php
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ public function getChild($name, $info = null, ?IRequest $request = null, ?IL10N
$path = $this->path . '/' . $name;
if (is_null($info)) {
try {
$this->fileView->verifyPath($this->path, $name);
$this->fileView->verifyPath($this->path, $name, true);
$info = $this->fileView->getFileInfo($path);
} catch (\OCP\Files\StorageNotAvailableException $e) {
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage(), 0, $e);
Expand Down
48 changes: 40 additions & 8 deletions lib/private/Files/View.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class View {
private bool $lockingEnabled;
private bool $updaterEnabled = true;
private UserManager $userManager;
private FilenameValidator $filenameValidator;
private LoggerInterface $logger;

/**
Expand All @@ -71,6 +72,7 @@ public function __construct(string $root = '') {
$this->lockingProvider = \OC::$server->get(ILockingProvider::class);
$this->lockingEnabled = !($this->lockingProvider instanceof \OC\Lock\NoopLockingProvider);
$this->userManager = \OC::$server->getUserManager();
$this->filenameValidator = \OCP\Server::get(FilenameValidator::class);
$this->logger = \OC::$server->get(LoggerInterface::class);
}

Expand Down Expand Up @@ -1097,7 +1099,7 @@ public function free_space($path = '/') {
* @throws LockedException
*
* This method takes requests for basic filesystem functions (e.g. reading & writing
* files), processes hooks and proxies, sanitises paths, and finally passes them on to
* files), processes hooks and proxies, sanitizes paths, and finally passes them on to
* \OC\Files\Storage\Storage for delegation to a storage backend for execution
*/
private function basicOperation(string $operation, string $path, array $hooks = [], $extraParam = null) {
Expand Down Expand Up @@ -1355,11 +1357,18 @@ public function getFileInfo($path, $includeMountPoints = true) {
return false;
}

if ($internalPath === '' && $data['name']) {
$data['name'] = basename($path);
}
if ($mount instanceof MoveableMount && $internalPath === '') {
$data['permissions'] |= \OCP\Constants::PERMISSION_DELETE;
}
if ($internalPath === '' && $data['name']) {
$data['name'] = basename($path);
// Ensure that parent path is valid (so it is writable)
try {
$this->verifyPath(dirname($path), basename($path));
} catch (InvalidPathException) {
// Not a valid parent path so remove update and create permissions
$data['permissions'] &= ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE);
}

$ownerId = $storage->getOwner($internalPath);
Expand Down Expand Up @@ -1439,17 +1448,26 @@ public function getDirectoryContent($directory, $mimetype_filter = '', ?\OCP\Fil
$contents = $cache->getFolderContentsById($folderId); //TODO: mimetype_filter

$sharingDisabled = \OCP\Util::isSharingDisabledForUser();
$folderIsReadonly = false;
try {
$this->verifyPath(dirname($directory), basename($directory));
} catch (InvalidPathException) {
$folderIsReadonly = true;
}

$fileNames = array_map(function (ICacheEntry $content) {
return $content->getName();
}, $contents);
/**
* @var \OC\Files\FileInfo[] $fileInfos
*/
$fileInfos = array_map(function (ICacheEntry $content) use ($path, $storage, $mount, $sharingDisabled) {
$fileInfos = array_map(function (ICacheEntry $content) use ($path, $storage, $mount, $sharingDisabled, $folderIsReadonly) {
if ($sharingDisabled) {
$content['permissions'] = $content['permissions'] & ~\OCP\Constants::PERMISSION_SHARE;
}
if ($folderIsReadonly) {
$content['permissions'] = $content['permissions'] & ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE);
}
$owner = $this->getUserObjectForOwner($storage->getOwner($content['path']));
return new FileInfo($path . '/' . $content['name'], $storage, $content['path'], $content, $mount, $owner);
}, $contents);
Expand Down Expand Up @@ -1517,6 +1535,9 @@ public function getDirectoryContent($directory, $mimetype_filter = '', ?\OCP\Fil
if ($sharingDisabled) {
$rootEntry['permissions'] = $rootEntry['permissions'] & ~\OCP\Constants::PERMISSION_SHARE;
}
if ($folderIsReadonly) {
$rootEntry['permissions'] = $rootEntry['permissions'] & ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE);
}

$owner = $this->getUserObjectForOwner($subStorage->getOwner(''));
$files[$rootEntry->getName()] = new FileInfo($path . '/' . $rootEntry['name'], $subStorage, '', $rootEntry, $mount, $owner);
Expand Down Expand Up @@ -1826,28 +1847,39 @@ private function getPartFileInfo(string $path): \OC\Files\FileInfo {
/**
* @param string $path
* @param string $fileName
* @param bool $readonly If the path should be verified for read-only operations
* @throws InvalidPathException
*/
public function verifyPath($path, $fileName): void {
public function verifyPath($path, $fileName, bool $readonly = false): void {
// All of the view's functions disallow '..' in the path so we can short cut if the path is invalid
if (!Filesystem::isValidPath($path ?: '/')) {
$l = \OCP\Util::getL10N('lib');
throw new InvalidPathException($l->t('Path contains invalid segments'));
}

// Handle filename validation for read-only operations, as we still allow to rename invalid files.
if ($readonly) {
// There is one exception: Forbidden files like `.htaccess` must not be accessible
if ($this->filenameValidator->isForbidden($fileName)) {
$l = \OCP\Util::getL10N('lib');
throw new InvalidPathException($l->t('Filename is a reserved word'));
}
return;
}

try {
/** @type \OCP\Files\Storage $storage */
[$storage, $internalPath] = $this->resolvePath($path);
$storage->verifyPath($internalPath, $fileName);
} catch (ReservedWordException $ex) {
$l = \OCP\Util::getL10N('lib');
throw new InvalidPathException($l->t('File name is a reserved word'));
throw new InvalidPathException($ex->getMessage() ?: $l->t('Filename is a reserved word'));
} catch (InvalidCharacterInPathException $ex) {
$l = \OCP\Util::getL10N('lib');
throw new InvalidPathException($l->t('File name contains at least one invalid character'));
throw new InvalidPathException($ex->getMessage() ?: $l->t('Filename contains at least one invalid character'));
} catch (FileNameTooLongException $ex) {
$l = \OCP\Util::getL10N('lib');
throw new InvalidPathException($l->t('File name is too long'));
throw new InvalidPathException($l->t('Filename is too long'));
} catch (InvalidDirectoryException $ex) {
$l = \OCP\Util::getL10N('lib');
throw new InvalidPathException($l->t('Dot files are not allowed'));
Expand Down

0 comments on commit 46303c8

Please sign in to comment.