diff options
Diffstat (limited to 'phpBB/includes/functions.php')
-rw-r--r-- | phpBB/includes/functions.php | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index c06c246082..e17bbfd080 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -484,6 +484,140 @@ function _hash_crypt_private($password, $setting, &$itoa64) } /** +* Global function for chmodding directories and files for internal use +* This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions. +* The function determines owner and group from common.php file and sets the same to the provided file. +* The function uses bit fields to build the permissions. +* The function sets the appropiate execute bit on directories. +* +* Supported constants representing bit fields are: +* +* CHMOD_ALL - all permissions (7) +* CHMOD_READ - read permission (4) +* CHMOD_WRITE - write permission (2) +* CHMOD_EXECUTE - execute permission (1) +* +* NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions. +* +* @param $filename The file/directory to be chmodded +* @param $perms Permissions to set +* @return true on success, otherwise false +* +* @author faw, phpBB Group +*/ +function phpbb_chmod($filename, $perms = CHMOD_READ) +{ + // Return if the file no longer exists. + if (!file_exists($filename)) + { + return false; + } + + if (!function_exists('fileowner') || !function_exists('filegroup')) + { + $file_uid = $file_gid = false; + $common_php_owner = $common_php_group = false; + } + else + { + // Determine owner/group of common.php file and the filename we want to change here + $common_php_owner = fileowner(PHPBB_ROOT_PATH . 'common.' . PHP_EXT); + $common_php_group = filegroup(PHPBB_ROOT_PATH . 'common.' . PHP_EXT); + + $file_uid = fileowner($filename); + $file_gid = filegroup($filename); + + // Try to set the owner to the same common.php has + if ($common_php_owner !== $file_uid && $common_php_owner !== false && $file_uid !== false) + { + // Will most likely not work + if (@chown($filename, $common_php_owner)); + { + $file_uid = fileowner($filename); + } + } + + // Try to set the group to the same common.php has + if ($common_php_group !== $file_gid && $common_php_group !== false && $file_gid !== false) + { + if (@chgrp($filename, $common_php_group)); + { + $file_gid = filegroup($filename); + } + } + } + + // And the owner and the groups PHP is running under. + $php_uid = (function_exists('posix_getuid')) ? @posix_getuid() : false; + $php_gids = (function_exists('posix_getgroups')) ? @posix_getgroups() : false; + + // Who is PHP? + if ($file_uid === false || $file_gid === false || $php_uid === false || $php_gids === false) + { + $php = null; + } + else if ($file_uid == $php_uid /* && $common_php_owner !== false && $common_php_owner === $file_uid*/) + { + $php = 'owner'; + } + else if (in_array($file_gid, $php_gids)) + { + $php = 'group'; + } + else + { + $php = 'other'; + } + + // Owner always has read/write permission + $owner = CHMOD_READ | CHMOD_WRITE; + if (is_dir($filename)) + { + $owner |= CHMOD_EXECUTE; + + // Only add execute bit to the permission if the dir needs to be readable + if ($perms & CHMOD_READ) + { + $perms |= CHMOD_EXECUTE; + } + } + + switch ($php) + { + case null: + case 'owner': + $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0)); + + if (!is_null($php) || (!is_readable($filename) && is_writable($filename))) + { + break; + } + + case 'group': + $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0)); + + if (!is_null($php) || ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename)))) + { + break; + } + + case 'other': + $result = @chmod($filename, ($owner << 6) + ($perms << 3) + ($perms << 0)); + + if (!is_null($php) || ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename)))) + { + break; + } + + default: + return false; + break; + } + + return $result; +} + +/* * Checks if a path ($path) is absolute or relative * * @param string $path Path to check absoluteness of |