From 233e62f0b5033e84964fff95d79497ba62a52f23 Mon Sep 17 00:00:00 2001 From: Meik Sievertsen Date: Wed, 18 Mar 2009 18:09:14 +0000 Subject: backport 3.2 version of phpbb_chmod() - need to be tested further... git-svn-id: file:///svn/phpbb/branches/phpBB-3_0_0@9394 89ea8834-ac86-4346-8a33-228a782c2dd0 --- phpBB/includes/functions.php | 128 +++++++++++++++++++++++++------------------ 1 file changed, 76 insertions(+), 52 deletions(-) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 65bf1f9c65..248a478145 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -461,8 +461,9 @@ 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. Permissions are mapped to the group, user always has rw(x) permission. +* 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. * @@ -475,76 +476,103 @@ function _hash_crypt_private($password, $setting, &$itoa64) * * 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 +* @param string $filename The file/directory to be chmodded +* @param int $perms Permissions to set * +* @return bool true on success, otherwise false * @author faw, phpBB Group */ function phpbb_chmod($filename, $perms = CHMOD_READ) { + static $_chmod_info; + // 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 some common vars + if (empty($_chmod_info)) { - global $phpbb_root_path, $phpEx; + if (!function_exists('fileowner') || !function_exists('filegroup')) + { + // No need to further determine owner/group - it is unknown + $_chmod_info['process'] = false; + } + else + { + global $phpbb_root_path, $phpEx; - // Determine owner/group of common.php file and the filename we want to change here - $common_php_owner = fileowner($phpbb_root_path . 'common.' . $phpEx); - $common_php_group = filegroup($phpbb_root_path . 'common.' . $phpEx); + // Determine owner/group of common.php file and the filename we want to change here + $common_php_owner = fileowner($phpbb_root_path . 'common.' . $phpEx); + $common_php_group = filegroup($phpbb_root_path . 'common.' . $phpEx); - $file_uid = fileowner($filename); - $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; - // 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)); + // If we are unable to get owner/group, then do not try to set them by guessing + if (!$php_uid || empty($php_gids) || !$common_php_owner || !$common_php_group) { - clearstatcache(); - $file_uid = fileowner($filename); + $_chmod_info['process'] = false; } - } - - // 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)); + else { - clearstatcache(); - $file_gid = filegroup($filename); + $_chmod_info = array( + 'process' => true, + 'common_owner' => $common_php_owner, + 'common_group' => $common_php_group, + 'php_uid' => $php_uid, + 'php_gids' => $php_gids, + ); } } } - // 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*/) + if ($_chmod_info['process']) { - $php = 'owner'; + // Change owner + if (@chown($filename, $_chmod_info['common_owner'])) + { + clearstatcache(); + $file_uid = fileowner($filename); + } + + // Change group + if (@chgrp($filename, $_chmod_info['common_group'])) + { + clearstatcache(); + $file_gid = filegroup($filename); + } + + // If the file_uid/gid now match the one from common.php we can process further, else we are not able to change something + if ($file_uid != $_chmod_info['common_owner'] || $file_gid != $_chmod_info['common_group']) + { + $_chmod_info['process'] = false; + } } - else if (in_array($file_gid, $php_gids)) + + // Still able to process? + if ($_chmod_info['process']) { - $php = 'group'; + if ($file_uid == $_chmod_info['php_uid']) + { + $php = 'owner'; + } + else if (in_array($file_gid, $_chmod_info['php_gids'])) + { + $php = 'group'; + } + else + { + // Since we are setting the everyone bit anyway, no need to do expensive operations + $_chmod_info['process'] = false; + } } - else + + // We are not able to determine or change something + if (!$_chmod_info['process']) { $php = 'other'; } @@ -564,26 +592,22 @@ function phpbb_chmod($filename, $perms = CHMOD_READ) switch ($php) { - case null: case 'owner': - /* ATTENTION: if php is owner or NULL we set it to group here. This is the most failsafe combination for the vast majority of server setups. - $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0)); clearstatcache(); - if (!is_null($php) || (is_readable($filename) && is_writable($filename))) + if (is_readable($filename) && is_writable($filename)) { break; } - */ case 'group': $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0)); clearstatcache(); - if (!is_null($php) || ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename)))) + if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename))) { break; } @@ -593,7 +617,7 @@ function phpbb_chmod($filename, $perms = CHMOD_READ) clearstatcache(); - if (!is_null($php) || ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename)))) + if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename))) { break; } -- cgit v1.2.1