From fcdc60ed681f95e4a1470302cbb9d39efd315fed Mon Sep 17 00:00:00 2001 From: Colan Schwartz Date: Mon, 9 Jul 2012 02:36:32 -0400 Subject: [PATCH] Issue #990812 by colan: Add "permissions" subcommand to fix ownership/perms. --- commands/perms/perms.drush.inc | 224 ++++++++++++++++++++++++++++++++++++++++ 1 files changed, 224 insertions(+), 0 deletions(-) create mode 100644 commands/perms/perms.drush.inc diff --git a/commands/perms/perms.drush.inc b/commands/perms/perms.drush.inc new file mode 100644 index 0000000..08d4e13 --- /dev/null +++ b/commands/perms/perms.drush.inc @@ -0,0 +1,224 @@ + "Fix permissions on files in the Drupal web directory. Group members will get full access to files. If not specified, the group will remain unchanged.", + 'arguments' => array( + 'web user' => 'The user name used by the web server.', + 'group owner' => 'The group that will own the files.', + ), + 'options' => array( + ), + 'examples' => array( + 'drush permissions www-data devs' => 'Set permissions with "www-data" as the web user and have the group "devs" own all files with its members having full access.', + 'drush perms apache' => 'Set permissions with "apache" as the web user; Don\'t change the group ownership, but group members will obtain full access.', + ), + 'aliases' => array('perms'), + // Just need the root directory. + 'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_ROOT, + ); + + return $items; +} + +/** + * Implementats hook_drush_help(). + */ +function perms_drush_help($section) { + switch ($section) { + case 'drush:permissions': + return dt("This command will Fix permissions on files in the Drupal web directory."); + } +} + +/* + * Implementats drush_hook_COMMAND_validate(). + */ +function drush_perms_permissions_validate($user_web = 'www-data', $group = NULL) { + + // Make sure that we've got a POSIX system. + if (!function_exists('posix_getpwuid')) { + return drush_set_error( + 'ERROR_NON_POSIX', + dt('Currently, this command can only be run on a POSIX system.') + ); + } + + // Make sure that the command is being run as an administrator. + $name = posix_getpwuid(posix_geteuid()); + if ($name['name'] !== 'root') { + return drush_set_error( + 'ERROR_MUST_BE_ROOT', + dt('You must be root to run this command by prefixing it with "sudo".') + ); + } +} + +/** + * Implements drush_COMMANDFILE_COMMANDNAME(). + */ +function drush_perms_permissions($user_web = 'www-data', $group = NULL) { + + // Get the Drupal root. + if (!$drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT')) { + return drush_set_error( + 'ERROR_CANNOT_GET_ROOT', + dt('Cannot determine the Drupal root directory.') + ); + } + + // Set the permissions. Assume that we always want full access for the group + // because the user gets to specify it. If it's not specified, leave the + // group ownership as is. + $perms_dir_user_read = 0575; + $perms_dir_user_both = 0775; + $perms_file_user_none = 0064; + $perms_file_user_read = 0464; + $perms_file_user_both = 0664; + $perms_file_user_read_no_other = 0460; + $perms_file_user_both_no_other = 0660; + + // Get the real username of who/whatever's running this. posix_getuid() + // shouldn't return "root" here, but it does so we can't use it. "sudo" + // seems to be confusing it. + @drush_shell_exec('echo $SUDO_USER'); + $output = drush_shell_exec_output(); + $user_running = $output[0]; + + // Create an iteration of files starting at the Drupal root. + $iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator( + $drupal_root, + RecursiveDirectoryIterator::FOLLOW_SYMLINKS + ), + RecursiveIteratorIterator::SELF_FIRST + ); + + // Iterate through all of the files. + foreach ($iterator as $current_file) { + + // If a group was provided, set it as the group owner. + if ($group) { + chgrp($current_file->getPathname(), $group); + } + + // Determine class (readability and writability) of the file or directory. + if (preg_match('/^[A-Z]+\.([a-z]+\.)?txt$/', $current_file->getFilename())) { + + /* + * This file is purely documentation for system adminstrators. It should + * not be read or written by the web server. + */ + + // Set proper ownership and permissions. + if (($user_running === 'root') || ($user_running === $user_web)) { + + // We don't have a non-root non-web user to become the owner. Handle + // this by setting the owner to the web user, but disable read and + // write access. + chown($current_file->getPathname(), $user_web); + chmod($current_file->getPathname(), $perms_file_user_none); + } + else { + + // We have a real non-root non-web user who's running this. He/she can + // become the owner, and we can allow him/her to read and write it. To + // make sure that the web user can't see this stuff, we have to disable + // world readability. + chown($current_file->getPathname(), $user_running); + chmod($current_file->getPathname(), $perms_file_user_both_no_other); + } + } + else if ($current_file->getFilename() == 'settings.php') { + + /* + * This is a settings.php file. These are special because the web server + * needs to be able to read it, but it shouldn't be read by anyone else + * as it contains password information. + */ + + // Set the owner to the web user, and disable readability for others. + chown($current_file->getPathname(), $user_web); + chmod($current_file->getPathname(), $perms_file_user_read_no_other); + } + else if (preg_match('/\/sites\/.*\/files($|\/)/', $current_file->getPathname())) { + + /* + * This file or directory is part of Drupal's file system for uploaded + * files. It needs to be readable and writable by the web server. + */ + + // Set the web user as the owner. + chown($current_file->getPathname(), $user_web); + + // Set full user permissions. + if ($iterator->isFile()) { + chmod($current_file->getPathname(), $perms_file_user_both); + } + else if ($iterator->isDir()) { + chmod($current_file->getPathname(), $perms_dir_user_both); + } + } + else { + + /* + * All remaining files and directories are readable, but not writable. + * It is theoretically possible for things to be writable and not + * readable, but there's no reason for this to ever happen on a Drupal + * site. + */ + + // Set proper ownership and permissions. + if (($user_running === 'root') || ($user_running === $user_web)) { + + /* + * We don't have a non-root non-web user to become the owner. + */ + + // Set the owner to the web user. + chown($current_file->getPathname(), $user_web); + + // Disable write access. + if ($iterator->isFile()) { + chmod($current_file->getPathname(), $perms_file_user_read); + } + else if ($iterator->isDir()) { + chmod($current_file->getPathname(), $perms_dir_user_read); + } + } + else { + + /* + * We have a real non-root non-web user who's running this. + */ + + // He/she can become the owner. + chown($current_file->getPathname(), $user_running); + + // We can allow him/her to read and write it. + if ($iterator->isFile()) { + chmod($current_file->getPathname(), $perms_file_user_both); + } + else if ($iterator->isDir()) { + chmod($current_file->getPathname(), $perms_dir_user_both); + } + } + } + } +} + -- 1.7.0.4