public function getGroups() { $gids = posix_getgroups(); $ret = []; foreach ($gids as $gid) { $ret[] = new Group($gid); } return $ret; }
public function get($name) { $data = posix_getpwnam($name); if ($data !== false) { $data['groups'] = array_map(function ($group) { $group = posix_getgrgid($group); return $group['name']; }, posix_getgroups()); } return $data; }
/** * @inheritdoc * * @return array */ function check() { if ($this->path[0] == '/') { $filename = $this->path; } else { $filename = BASE_PATH . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $this->path); } if (file_exists($filename)) { $isWriteable = is_writeable($filename); } else { $isWriteable = is_writeable(dirname($filename)); } if (!$isWriteable) { if (function_exists('posix_getgroups')) { $userID = posix_geteuid(); $user = posix_getpwuid($userID); $currentOwnerID = fileowner(file_exists($filename) ? $filename : dirname($filename)); $currentOwner = posix_getpwuid($currentOwnerID); $message = "User '{$user['name']}' needs to be able to write to this file:\n{$filename}\n\nThe file is currently owned by '{$currentOwner['name']}'. "; if ($user['name'] == $currentOwner['name']) { $message .= "We recommend that you make the file writeable."; } else { $groups = posix_getgroups(); $groupList = array(); foreach ($groups as $group) { $groupInfo = posix_getgrgid($group); if (in_array($currentOwner['name'], $groupInfo['members'])) { $groupList[] = $groupInfo['name']; } } if ($groupList) { $message .= "\tWe recommend that you make the file group-writeable and change the group to one of these groups:\n - " . implode("\n - ", $groupList) . "\n\nFor example:\nchmod g+w {$filename}\nchgrp " . $groupList[0] . " {$filename}"; } else { $message .= " There is no user-group that contains both the web-server user and the owner of this file. Change the ownership of the file, create a new group, or temporarily make the file writeable by everyone during the install process."; } } } else { $message = "The webserver user needs to be able to write to this file:\n{$filename}"; } return array(EnvironmentCheck::ERROR, $message); } return array(EnvironmentCheck::OK, ''); }
function have_direct_access() { if (!is_null($this->have_direct_access)) { return $this->have_direct_access; } $this->have_direct_access = false; if (!function_exists('getmyuid') || !function_exists('fileowner') || !function_exists('posix_getgroups') || !function_exists('filegroup')) { return $this->have_direct_access; } $temp_file_name = $this->config->root_path . '/temp-write-test-' . time(); $temp_handle = @fopen($temp_file_name, 'w'); if ($temp_handle) { if (getmyuid() == @fileowner($temp_file_name) || in_array(@filegroup($temp_file_name), posix_getgroups())) { $this->have_direct_access = true; } @fclose($temp_handle); @unlink($temp_file_name); } return $this->have_direct_access; }
$gmembers = array(); foreach ($ginfo['members'] as $index => $label) { $gmembers[] = $label; } if (count($gmembers)) { $glabel .= ' (' . implode(', ', $gmembers) . ')'; } } } // display gathered information echo '<p>' . i18n::s('user/group of this script:') . ' ' . $ulabel . '/' . $glabel . "</p>\n"; } else { echo '<p>' . i18n::s('Impossible to retrieve user/group of this script.') . "</p>\n"; } // user/group of this process if (is_callable('posix_geteuid') && ($uid = posix_geteuid()) !== FALSE && is_callable('posix_getgroups') && ($gids = posix_getgroups()) !== FALSE) { // describe user $ulabel = $uid; if (is_callable('posix_getpwuid') && ($uinfo = posix_getpwuid($uid)) !== FALSE) { if (isset($uinfo['name'])) { $ulabel = $uinfo['name'] . '[' . $uid . ']'; } } // describe groups $glabel = ''; foreach ($gids as $gid) { // group name if (is_callable('posix_getgrgid') && ($ginfo = posix_getgrgid($gid)) !== FALSE && isset($ginfo['name'])) { $glabel .= $ginfo['name'] . '[' . $gid . ']'; } else { $glabel .= $gid;
function isInFossyGroup() { $gid_array = posix_getgroups(); foreach ($gid_array as $gid) { $gid_info = posix_getgrgid($gid); if ($gid_info['name'] === 'fossy') { return true; } } $uid = posix_getuid(); $uid_info = posix_getpwuid($uid); return $uid_info['name'] !== 'root'; }
/** * Run a MediaWiki script based on the parameters (like --wiki) given to CLI. * * The first argument must be the relative (to MediaWiki) script file path. * If only a filename is given, it will be assumed to reside in /maintenance. * The second argument must be the --wiki parameter. This is to avoid * any "options with args" ambiguity (see Maintenance.php). * * When the actual script is run, $argv[0] (this file's name) will be not be kept. * Also, $argv[1] (the script path) will be changed to the script file name. * All other arguments will be preserved. * * @return string Absolute MediaWiki script path */ function getMWScriptWithArgs() { global $argv; if (count($argv) < 2) { fwrite(STDERR, "This script can only be run from the command line.\n"); exit(1); } # Security check -- don't allow scripts to run as privileged users $gids = posix_getgroups(); foreach ($gids as $gid) { $info = posix_getgrgid($gid); if ($info && in_array($info['name'], array('sudo', 'wikidev', 'root'))) { fwrite(STDERR, "Cannot run a MediaWiki script as a user in the " . "group {$info['name']}\n"); fwrite(STDERR, <<<EOT Maintenance scripts should generally be run using sudo -u www-data which is available to all wikidev users. Running a maintenance script as a privileged user risks compromise of the user account. You should run this script as the www-data user: sudo -u www-data <command> EOT ); exit(1); } } $relFile = $argv[1]; // the script file to run # If no MW directory is given then assume this is a /maintenance script if (strpos($relFile, '/') === false) { $relFile = "maintenance/{$relFile}"; // convenience } # Remove effects of this wrapper from $argv... array_shift($argv); // remove this file's name from args # Code stolen from wfBasename() in GlobalFunctions.php :) if (preg_match("#([^/\\\\]*?)[/\\\\]*\$#", $argv[0], $matches)) { $argv[0] = $matches[1]; // make first arg the script file name } # For addwiki.php, the wiki DB doesn't yet exist, and for some # other maintenance scripts we don't care what wiki DB is used... $wikiless = array('maintenance/purgeList.php', 'extensions/WikimediaMaintenance/addWiki.php', 'extensions/WikimediaMaintenance/dumpInterwiki.php', 'extensions/WikimediaMaintenance/getJobQueueLengths.php', 'extensions/WikimediaMaintenance/rebuildInterwiki.php', 'extensions/WikimediaMaintenance/filebackend/setZoneAccess.php', 'maintenance/mctest.php', 'maintenance/mcc.php'); # Check if a --wiki param was given... # Maintenance.php will treat $argv[1] as the wiki if it doesn't start '-' if (!isset($argv[1]) || !preg_match('/^([^-]|--wiki(=|$))/', $argv[1])) { if (in_array($relFile, $wikiless)) { # Assume aawiki as Maintenance.php does. $argv = array_merge(array($argv[0], "--wiki=aawiki"), array_slice($argv, 1)); } } # MWScript.php should be in common/ require_once __DIR__ . '/MWVersion.php'; $file = getMediaWikiCli($relFile); if (!file_exists($file)) { fwrite(STDERR, "The MediaWiki script file \"{$file}\" does not exist.\n"); exit(1); } return $file; }
/** * Get groups * * @return array */ public function getgroups() { return posix_getgroups(); }
function is_writable_or_chmodable($fn) { $stat = stat($fn); if (!$stat) { return false; } $myuid = posix_getuid(); $mygids = posix_getgroups(); if ($myuid == 0 || $myuid == $stat['uid'] || in_array($stat['gid'], $mygids) && $stat['mode'] & 020 || $stat['mode'] & 02) { return true; } return false; }
/** * Check if test on filesystem group ownership can be done in this environment * If so, return second group of webserver user * * @param string calling method name * @return mixed FALSE if test cannot be run, string name of the second group of webserver user */ private function checkGroups($methodName) { if (TYPO3_OS == 'WIN') { $this->markTestSkipped($methodName . '() test not available on Windows.'); return FALSE; } if (!function_exists('posix_getgroups')) { $this->markTestSkipped('Function posix_getgroups() not available, ' . $methodName . '() tests skipped'); } $groups = posix_getgroups(); if (count($groups) <= 1) { $this->markTestSkipped($methodName . '() test cannot be done when the web server user is only member of 1 group.'); return FALSE; } $groupInfo = posix_getgrgid($groups[1]); return $groupInfo['name']; }
/** * @author faw, phpBB Group and Kleeja team */ function _chmod($filepath, $perm = 0644) { static $continue; if (empty($continue)) { if (!function_exists('fileowner') || !function_exists('filegroup')) { #if we cant get those data, no need to complete the check $continue['process'] = false; } else { #get the owner and group of the common.php file, why common.php? it's the master $common_php_owner = @fileowner(PATH . 'includes/common.php'); $common_php_group = @filegroup(PATH . 'includes/common.php'); // 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; // 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) { $continue['process'] = false; } else { $continue = array('process' => true, 'common_owner' => $common_php_owner, 'common_group' => $common_php_group, 'php_uid' => $php_uid, 'php_gids' => $php_gids); } } } # From static, or not .. lets continue if ($continue['process']) { $file_uid = @fileowner($this->_fixpath($filepath)); $file_gid = @filegroup($this->_fixpath($filepath)); // Change owner if (@chown($this->_fixpath($filepath), $continue['common_owner'])) { clearstatcache(); $file_uid = @fileowner($this->_fixpath($filepath)); } // Change group if (@chgrp($this->_fixpath($filepath), $continue['common_group'])) { clearstatcache(); $file_gid = @filegroup($this->_fixpath($filepath)); } // 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 != $continue['common_owner'] || $file_gid != $continue['common_group']) { $continue['process'] = false; } } # Still able to process? if ($continue['process']) { if ($file_uid == $continue['php_uid']) { $php = 'owner'; } else { if (in_array($file_gid, $continue['php_gids'])) { $php = 'group'; } else { // Since we are setting the everyone bit anyway, no need to do expensive operations $continue['process'] = false; } } } // We are not able to determine or change something if (!$continue['process']) { $php = 'other'; } // Owner always has read/write permission $owner = 4 | 2; if (is_dir($this->_fixpath($filepath))) { $owner |= 1; // Only add execute bit to the permission if the dir needs to be readable if ($perm & 4) { $perm |= 1; } } switch ($php) { case 'owner': $result = @chmod($this->_fixpath($filepath), ($owner << 6) + (0 << 3) + (0 << 0)); clearstatcache(); if (is_readable($this->_fixpath($filepath)) && is_writable($this->_fixpath($filepath))) { break; } case 'group': $result = @chmod($this->_fixpath($filepath), ($owner << 6) + ($perm << 3) + (0 << 0)); clearstatcache(); if ((!($perm & 4) || is_readable($this->_fixpath($filepath))) && (!($perm & 2) || is_writable($this->_fixpath($filepath)))) { break; } case 'other': $result = @chmod($this->_fixpath($filepath), ($owner << 6) + ($perm << 3) + ($perm << 0)); clearstatcache(); if ((!($perm & 4) || is_readable($this->_fixpath($filepath))) && (!($perm & 2) || is_writable($this->_fixpath($filepath)))) { break; } default: return false; break; } # if nothing works well use the handler... if (!$result) { $result = $this->f->_chmod($this->_fixpath($filepath), $perm); } return $result; }
* The name of the testrepo will be in the fossology.conf file in the test * configuration directory. * * This program can be called to drop the DB and clean up. * * @version "$Id$" * * Created on Sep 14, 2011 by Mark Donohoe */ require_once __DIR__ . '/../lib/libTestDB.php'; $Options = getopt('c:d:esh'); $usage = $argv[0] . ": [-h] -c path [-d name] [-s]\n" . "-c path: The path to the fossology system configuration directory\n" . "-d name: Drop the named data base.\n" . "-e: create ONLY an empty db, sysconf dir and repository\n" . "-h: This message (Usage)\n" . "-s: Start the scheduler with the new sysconfig directory\n" . "Examples:\n" . " Create a test DB: 'createTestDb.php' \n" . " Drop the database fosstest1537938: 'createTestDb.php -d fosstest1537938'\n" . " Create test DB, start scheduler: 'createTestDb.php -s'\n" . " Create empty DB, sysconf and repo: 'createTestDb.php -e'\n"; $pathPrefix = '/srv/fossology'; $dbPrefix = 'fosstest'; // check if the user is in the fossy group $gid_array = posix_getgroups(); $gflag = 0; // 0: in the fossy group, 1: not in the fossy group foreach ($gid_array as $gid) { $gid_info = posix_getgrgid($gid); if ($gid_info['name'] === 'fossy') { $gflag = 1; // the user is in fossy group break; } } $uid = posix_getuid(); $uid_info = posix_getpwuid($uid); if ($uid_info['name'] === 'root') { $gflag = 1; }
/** * Check if test on filesystem group ownership can be done in this environment * If so, return second group of webserver user * * @param string calling method name * @return mixed FALSE if test cannot be run, string name of the second group of webserver user */ private function checkGroups($methodName) { if (TYPO3_OS == 'WIN') { $this->markTestSkipped($methodName . '() test not available on Windows.'); return false; } if (!function_exists('posix_getgroups')) { $this->markTestSkipped('Function posix_getgroups() not available, ' . $methodName . '() tests skipped'); } $groups = posix_getgroups(); if (count($groups) <= 1) { $this->markTestSkipped($methodName . '() test cannot be done when the web server user is only member of 1 group.'); return false; } $uname = strtolower(php_uname()); $groupOffset = 1; if (strpos($uname, 'darwin') !== false) { // We are on OSX and it seems that the first group needs to be fetched since Mavericks $groupOffset = 0; } $groupInfo = posix_getgrgid($groups[$groupOffset]); return $groupInfo['name']; }
/** * Get the number of bits to shift to get the privileges of the user of the current process. * * {@example * $mode = ($file['mode'] >> $file->modeBitShift()) & 7; // Privileges for the current user as bitset (rwx) * $privs = substr($file['privs'], 7 - $file->modeBitShift(), 3); // Privileges for the current user as string * }} * * @param int $flags FS::% options * @return int * @throws Exception if posix extension is not available. */ public function modeBitShift($user, $flags = 0) { if (!extension_loaded('posix')) { throw new Exception("Unable to determine the which part of the mode of '{$this->_path}' applies to the current user: Posix extension not avaible."); } return $this->getAttribute('uid', $flags) == posix_getuid() ? 6 : (in_array($this->getAttribute('gid', $flags), posix_getgroups()) ? 3 : 0); }
echo "gid={$gid}\n"; $egid = posix_getegid(); echo "egid={$egid}\n"; posix_setuid(1004); $uid = posix_getuid(); echo "uid={$uid}\n"; posix_seteuid(1004); $euid = posix_geteuid(); echo "euid={$euid}\n"; posix_setgid(1004); $gid = posix_getgid(); echo "gid={$gid}\n"; posix_setegid(1004); $egid = posix_getegid(); echo "egid={$egid}\n"; $groups = posix_getgroups(); echo "groups=\n"; print_r($groups); $login = posix_getlogin(); echo "login={$login}\n"; $pgrp = posix_getpgrp(); echo "pgrp={$pgrp}\n"; $setsid = posix_setsid(); if ($setsid > 0) { echo "posix_setsid succeeded\n"; } else { echo "posix_setsid failed\n"; } $getpgid = posix_getpgid($pid); if ($getpgid > 0) { echo "posix_getpgid succeeded\n";
/** * Return the group set of the current process * * @return array */ public function getgroups() : array { return posix_getgroups(); }
/** * Вход в консоль Pinger. * * @param array $argv Копия массива <code>$argv</code> с аргументами вызова скрипта. * @return void * @access protected * @static */ public static function main($argv) { if ('cli' !== PHP_SAPI) { die("CLI only!"); } if (!count(array_intersect(posix_getgroups(), [0, posix_getgrnam('pinger')['gid']]))) { echo "Error: Pinger Console must be launched as root or from group named 'pinger'!\n"; exit(1); } $argv += array_fill(0, 4, null); switch ($argv[1]) { case 'list': static::cmdList(); break; case 'add': static::cmdAdd($argv[2], $argv[3]); break; case 'rem': static::cmdRem($argv[2]); break; case 'enable': static::cmdEnable($argv[2]); break; case 'disable': static::cmdDisable($argv[2]); break; case 'help': default: static::cmdHelp($argv[1]); break; } }
/** * Returns an array of data returned from the UNIX 'id' command * * includes uid, username, gid, groupname, and groups (if "exec" * is enabled). Groups is an array of all the groups the user * belongs to. Keys are the group ids, values are the group names. * * returns FALSE if no suitable function is available to retrieve * the data * * @return array|boolean */ function getUnixId() { if ($this->osIsWindows()) { return false; } $success = false; if (function_exists("exec") && !PhpSecInfo_Test::getBooleanIniValue('safe_mode')) { $id_raw = exec('id'); // uid=1000(coj) gid=1000(coj) groups=1000(coj),1001(admin) preg_match( "|uid=(\d+)\((\S+)\)\s+gid=(\d+)\((\S+)\)\s+groups=(.+)|i", $id_raw, $matches); if (!$matches) { /** * for some reason the output from 'id' wasn't as we expected. * return false so the test doesn't run. */ $success = false; } else { $id_data = array( 'uid'=>$matches[1], 'username'=>$matches[2], 'gid'=>$matches[3], 'group'=>$matches[4] ); $groups = array(); if ($matches[5]) { $gs = $matches[5]; $gs = explode(',', $gs); foreach ($gs as $groupstr) { if (preg_match("/(\d+)\(([^\)]+)\)/", $groupstr, $subs)) { $groups[$subs[1]] = $subs[2]; } else { $groups[$groupstr] = ''; } } ksort($groups); } $id_data['groups'] = $groups; $success = true; } } if (!$success && function_exists("posix_getpwuid") && function_exists("posix_geteuid") && function_exists('posix_getgrgid') && function_exists('posix_getgroups') ) { $data = posix_getpwuid( posix_getuid() ); $id_data['uid'] = $data['uid']; $id_data['username'] = $data['name']; $id_data['gid'] = $data['gid']; //$group_data = posix_getgrgid( posix_getegid() ); //$id_data['group'] = $group_data['name']; $id_data['groups'] = array(); $groups = posix_getgroups(); foreach ( $groups as $gid ) { //$group_data = posix_getgrgid(posix_getgid()); $id_data['groups'][$gid] = '<unknown>'; } $success = true; } if ($success) { return $id_data; } else { return false; } }
public function requireWriteable($filename, $testDetails, $absolute = false) { $this->testing($testDetails); if ($absolute) { $filename = str_replace('/', DIRECTORY_SEPARATOR, $filename); } else { $filename = $this->getBaseDir() . str_replace('/', DIRECTORY_SEPARATOR, $filename); } if (file_exists($filename)) { $isWriteable = is_writeable($filename); } else { $isWriteable = is_writeable(dirname($filename)); } if (!$isWriteable) { if (function_exists('posix_getgroups')) { $userID = posix_geteuid(); $user = posix_getpwuid($userID); $currentOwnerID = fileowner(file_exists($filename) ? $filename : dirname($filename)); $currentOwner = posix_getpwuid($currentOwnerID); $testDetails[2] .= "User '{$user['name']}' needs to be able to write to this file:\n{$filename}\n\nThe " . "file is currently owned by '{$currentOwner['name']}'. "; if ($user['name'] == $currentOwner['name']) { $testDetails[2] .= "We recommend that you make the file writeable."; } else { $groups = posix_getgroups(); $groupList = array(); foreach ($groups as $group) { $groupInfo = posix_getgrgid($group); if (in_array($currentOwner['name'], $groupInfo['members'])) { $groupList[] = $groupInfo['name']; } } if ($groupList) { $testDetails[2] .= "\tWe recommend that you make the file group-writeable " . "and change the group to one of these groups:\n - " . implode("\n - ", $groupList) . "\n\nFor example:\nchmod g+w {$filename}\nchgrp " . $groupList[0] . " {$filename}"; } else { $testDetails[2] .= " There is no user-group that contains both the web-server user and the " . "owner of this file. Change the ownership of the file, create a new group, or " . "temporarily make the file writeable by everyone during the install process."; } } } else { $testDetails[2] .= "The webserver user needs to be able to write to this file:\n{$filename}"; } $this->error($testDetails); } }
/** * Check if test on filesystem group ownership can be done in this environment * If so, return second group of webserver user * * @param string $methodName calling method name * @return mixed FALSE if test cannot be run, int group id of the second group of webserver user */ private function checkGroups($methodName) { if (TYPO3_OS === 'WIN') { $this->markTestSkipped($methodName . '() test not available on Windows.'); return false; } if (!function_exists('posix_getegid')) { $this->markTestSkipped('Function posix_getegid() not available, ' . $methodName . '() tests skipped'); return false; } if (posix_getegid() === -1) { $this->markTestSkipped('Function posix_getegid() returns -1, ' . $methodName . '() tests skipped'); return false; } if (!function_exists('posix_getgroups')) { $this->markTestSkipped('Function posix_getgroups() not available, ' . $methodName . '() tests skipped'); return false; } $groups = posix_getgroups(); if (count($groups) <= 1) { $this->markTestSkipped($methodName . '() test cannot be done when the web server user is only member of 1 group.'); return false; } $secondaryGroups = array_diff($groups, [posix_getegid()]); return array_shift($secondaryGroups); }
/** * 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 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; } // Determine some common vars if (empty($_chmod_info)) { 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); // 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; // 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) { $_chmod_info['process'] = false; } else { $_chmod_info = array('process' => true, 'common_owner' => $common_php_owner, 'common_group' => $common_php_group, 'php_uid' => $php_uid, 'php_gids' => $php_gids); } } } if ($_chmod_info['process']) { $file_uid = @fileowner($filename); $file_gid = @filegroup($filename); // 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; } } // Still able to process? if ($_chmod_info['process']) { 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; } } } // We are not able to determine or change something if (!$_chmod_info['process']) { $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 'owner': $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0)); clearstatcache(); if (is_readable($filename) && is_writable($filename)) { break; } case 'group': $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0)); clearstatcache(); if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename))) { break; } case 'other': $result = @chmod($filename, ($owner << 6) + ($perms << 3) + ($perms << 0)); clearstatcache(); if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename))) { break; } default: return false; break; } return $result; }
/** * Returns an array of data returned from the UNIX 'id' command * * includes uid, username, gid, groupname, and groups (if "exec" * is enabled). Groups is an array of all the groups the user * belongs to. Keys are the group ids, values are the group names. * * returns FALSE if no suitable function is available to retrieve * the data * * @return array|boolean */ function getUnixId() { if ($this->osIsWindows()) { return false; } elseif (function_exists("exec") && !PhpSecInfo_Test::getBooleanIniValue('safe_mode')) { $id_raw = exec('id'); // uid=1000(coj) gid=1000(coj) groups=1000(coj),1001(admin) preg_match("|uid=(\\d+)\\((\\S+)\\)\\s+gid=(\\d+)\\((\\S+)\\)\\s+groups=(.+)|i", $id_raw, $matches); $id_data = array('uid' => $matches[1], 'username' => $matches[2], 'gid' => $matches[3], 'group' => $matches[4]); if ($matches[5]) { $gs = $matches[5]; $gs = explode(',', $gs); foreach ($gs as $groupstr) { preg_match("/(\\d+)\\(([^\\)]+)\\)/", $groupstr, $subs); $groups[$subs[1]] = $subs[2]; } ksort($groups); $id_data['groups'] = $groups; } return $id_data; } elseif (function_exists("posix_getpwuid") && function_exists("posix_geteuid") && function_exists('posix_getgrgid') && function_exists('posix_getgroups')) { $data = posix_getpwuid(posix_getuid()); $id_data['uid'] = $data['uid']; $id_data['username'] = $data['name']; $id_data['gid'] = $data['gid']; //$group_data = posix_getgrgid( posix_getegid() ); //$id_data['group'] = $group_data['name']; $groups = posix_getgroups(); foreach ($groups as $gid) { //$group_data = posix_getgrgid(posix_getgid()); $id_data['groups'][$gid] = '<unknown>'; } } return false; }
/** * 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 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 { 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); $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)) { } clearstatcache(); $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)) { } clearstatcache(); $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) { $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': /* 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))) { break; } */ /* 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))) { 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))) { break; } case 'other': $result = @chmod($filename, ($owner << 6) + ($perms << 3) + ($perms << 0)); clearstatcache(); if (!is_null($php) || (!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename))) { break; } default: return false; break; } return $result; }
/** * {@inheritdoc} */ public function phpbb_chmod($files, $perms = null, $recursive = false, $force_chmod_link = false) { if (is_null($perms)) { // Default to read permission for compatibility reasons $perms = self::CHMOD_READ; } if (empty($this->chmod_info)) { if (!function_exists('fileowner') || !function_exists('filegroup')) { $this->chmod_info['process'] = false; } else { $common_php_owner = @fileowner(__FILE__); $common_php_group = @filegroup(__FILE__); // And the owner and the groups PHP is running under. $php_uid = function_exists('posic_getuid') ? @posix_getuid() : false; $php_gids = function_exists('posix_getgroups') ? @posix_getgroups() : false; // 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) { $this->chmod_info['process'] = false; } else { $this->chmod_info = array('process' => true, 'common_owner' => $common_php_owner, 'common_group' => $common_php_group, 'php_uid' => $php_uid, 'php_gids' => $php_gids); } } } if ($this->chmod_info['process']) { try { foreach ($this->to_iterator($files) as $file) { $file_uid = @fileowner($file); $file_gid = @filegroup($file); // Change owner if ($file_uid !== $this->chmod_info['common_owner']) { $this->chown($file, $this->chmod_info['common_owner'], $recursive); } // Change group if ($file_gid !== $this->chmod_info['common_group']) { $this->chgrp($file, $this->chmod_info['common_group'], $recursive); } clearstatcache(); $file_uid = @fileowner($file); $file_gid = @filegroup($file); } } catch (filesystem_exception $e) { $this->chmod_info['process'] = false; } } // Still able to process? if ($this->chmod_info['process']) { if ($file_uid === $this->chmod_info['php_uid']) { $php = 'owner'; } else { if (in_array($file_gid, $this->chmod_info['php_gids'])) { $php = 'group'; } else { // Since we are setting the everyone bit anyway, no need to do expensive operations $this->chmod_info['process'] = false; } } } // We are not able to determine or change something if (!$this->chmod_info['process']) { $php = 'other'; } switch ($php) { case 'owner': try { $this->chmod($files, $perms, $recursive, $force_chmod_link); clearstatcache(); if ($this->is_readable($files) && $this->is_writable($files)) { break; } } catch (filesystem_exception $e) { // Do nothing } case 'group': try { $this->chmod($files, $perms, $recursive, $force_chmod_link); clearstatcache(); if ((!($perms & self::CHMOD_READ) || $this->is_readable($files, $recursive)) && (!($perms & self::CHMOD_WRITE) || $this->is_writable($files, $recursive))) { break; } } catch (filesystem_exception $e) { // Do nothing } case 'other': default: $this->chmod($files, $perms, $recursive, $force_chmod_link); break; } }