Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 2927: create a method for checking if filename is a directory and also checking open_basedir #21923

Closed
wants to merge 6 commits into from

Conversation

herbdool
Copy link
Contributor

@herbdool herbdool commented Oct 25, 2021

Fixes https://lab.civicrm.org/dev/core/-/issues/2927

Overview

Create a method for checking if filename is a directory and also checking open_basedir. Use it instead of is_dir() which throws errors if not within the open_basedir restrictions.

Alternative to #21591

@civibot
Copy link

civibot bot commented Oct 25, 2021

(Standard links)

@civibot civibot bot added the master label Oct 25, 2021
CRM/Utils/File.php Outdated Show resolved Hide resolved
@seamuslee001
Copy link
Contributor

@agileware-justin do you have any comments on this given you seem to have been the one to hit the most openbase_dir issues

@agileware-justin
Copy link
Contributor

Thanks @seamuslee001

My initial thought is should all instances of is_dir be replaced, as indicated by #21592

@herbdool
Copy link
Contributor Author

herbdool commented Oct 26, 2021

@seamuslee001 @agileware-justin I agree with @demeritcowboy in this comment #21592 (comment) where they mention an attempt to remove the error suppression throughout the code. The PR #21592 is adding them, so it seems to be at cross-purposes. I took the approach suggested by "Another option 3 might be a wrapper function for is_dir that checks if open_basedir is being used."

@demeritcowboy
Copy link
Contributor

Probably most of them are ok to replace, especially if they are doing something like hunting for a file, but it depends on the specific instance. For example this one should output the warning about open_basedir, since otherwise you have to hunt harder to figure out the problem.

if (empty($this->baseDir) || !is_dir($this->baseDir)) {
$errors[] = [
'title' => ts('Invalid Base Directory'),
'message' => ts('An extension container has been defined with a blank directory.'),
];
.

@demeritcowboy
Copy link
Contributor

I'm willing to help out writing a test for this, since if replacing a core php function it should be unit-tested to act as close to is_dir as possible.

And I know I said to use strncasecmp() but now it technically can return the wrong thing on unix. I'm thinking now something like:

$compareFunc = 'strncmp';
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
  $compareFunc = 'strncasecmp';
}
if ($compareFunc($fileName, $baseDir ...etc...

@herbdool
Copy link
Contributor Author

@demeritcowboy thanks for your help. What do you think of my thought here https://lab.civicrm.org/dev/core/-/issues/2927#note_66686

$baseDirs = explode(PATH_SEPARATOR, $openBasedir);
$withinBasedir = FALSE;
foreach ($baseDirs as $baseDir) {
if ($compareFunc($filepath, $baseDir, strlen($baseDir)) === 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be filePath with a capital P.

I ran the tests against this and this function would need to deal with paths that have .. or . in them, because this algorithm doesn't quite work with them. Using realpath() might work. There is an existing function CRM_Utils_File::isChildPath() but it doesn't work on windows (it only seems to be used lightly for the extension manager).

@herbdool
Copy link
Contributor Author

Closing in favour of #22107

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants