From 8c020c0774dced0cf91d1aa954421c55ef502fac Mon Sep 17 00:00:00 2001 From: Dries Buytaert <dries@buytaert.net> Date: Fri, 8 Dec 2006 11:54:04 +0000 Subject: [PATCH] - Patch #101829 by douggreen, ChrisKennedy and Grugnog2: drupal_install_fix_file() fails to calculate correct permissions. --- includes/install.inc | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/includes/install.inc b/includes/install.inc index 4dfdbae958cd..06b25a77cfb5 100644 --- a/includes/install.inc +++ b/includes/install.inc @@ -485,6 +485,15 @@ function drupal_install_mkdir($file, $mask, $message = TRUE) { /** * Attempt to fix file permissions. * + * The general approach here is that, because we do not know the security + * setup of the webserver, we apply our permission changes to all three + * digits of the file permission (i.e. user, group and all). + * + * To ensure that the values behave as expected (and numbers don't carry + * from one digit to the next) we do the calculation on the octal value + * using bitwise operations. This lets us remove, for example, 0222 from + * 0700 and get the correct value of 0500. + * * @param $file * The name of the file with permissions to fix. * @param $mask @@ -496,48 +505,54 @@ function drupal_install_mkdir($file, $mask, $message = TRUE) { * TRUE/FALSE whether or not we were able to fix the file's permissions. */ function drupal_install_fix_file($file, $mask, $message = TRUE) { - $mod = substr(sprintf('%o', fileperms($file)), -4); - $prefix = substr($mod, 0, 1); - $mod = substr($mod, 1 ,4); + $mod = fileperms($file) & 0777; $masks = array(FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE); + + // FILE_READABLE, FILE_WRITABLE, and FILE_EXECUTABLE permission strings + // can theoretically be 0400, 0200, and 0100 respectively, but to be safe + // we set all three access types in case the administrator intends to + // change the owner of settings.php after installation. foreach ($masks as $m) { if ($mask & $m) { switch ($m) { case FILE_READABLE: if (!is_readable($file)) { - $mod += 444; + $mod |= 0444; } break; case FILE_WRITABLE: if (!is_writable($file)) { - $mod += 222; + $mod |= 0222; } break; case FILE_EXECUTABLE: if (!is_executable($file)) { - $mod += 111; + $mod |= 0111; } break; case FILE_NOT_READABLE: if (is_readable($file)) { - $mod -= 444; + $mod &= ~0444; } break; case FILE_NOT_WRITABLE: if (is_writable($file)) { - $mod -= 222; + $mod &= ~0222; } break; case FILE_NOT_EXECUTABLE: if (is_executable($file)) { - $mod -= 111; + $mod &= ~0111; } break; } } } - if (@chmod($file, intval("$prefix$mod", 8))) { + // chmod() will work if the web server is running as owner of the file. + // If PHP safe_mode is enabled the currently executing script must also + // have the same owner. + if (@chmod($file, $mod)) { return TRUE; } else { -- GitLab