array( "username" => "user:root", "runas" => "user:root", "cmdlist" => "ALL" ), 1 => array( "username" => "user:admin", "runas" => "user:root", "cmdlist" => "ALL" ), 2 => array( "username" => "group:admins", "runas" => "user:root", "cmdlist" => "ALL" ) ); } } function sudo_write_config() { global $config, $pfs_version; $sudoers = ""; if ($pfs_version == "2.2") { mwexec_bg("/sbin/ldconfig -m /usr/pbi/sudo-" . php_uname("m") . "/local/lib/"); } conf_mount_rw(); $sudoconf = "Plugin sudoers_policy " . SUDO_LIBEXEC_DIR . "/sudoers.so\n"; $sudoconf .= "Plugin sudoers_io " . SUDO_LIBEXEC_DIR . "/sudoers.so\n"; $sudoconf .= "Path noexec " . SUDO_LIBEXEC_DIR . "/sudo_noexec.so\n"; file_put_contents(SUDO_CONF, $sudoconf); if (!is_array($config['installedpackages']['sudo']['config'][0]['row'])) { /* No config, wipe sudoers file and bail. */ unlink(SUDO_SUDOERS); log_error("No sudo configuration found, removing sudoers file to prevent unpredictable results."); return; } $sudocfg = &$config['installedpackages']['sudo']['config'][0]['row']; /* Parse the config and massage it into proper sudo config lines. */ foreach ($sudocfg as $sudo_commands) { // (user|group) ALL=(ALL|user spec) ALL|command list list($etype, $ename) = explode(":", $sudo_commands['username']); $user = ($etype == "group") ? "%{$ename}" : $ename; list($rtype, $rname) = explode(":", $sudo_commands['runas']); $runas = ($rtype == "group") ? ":{$rname}" : $rname; $nopasswd = ($sudo_commands['nopasswd'] == "ON") ? "NOPASSWD:" : ""; $commands = (empty($sudo_commands['cmdlist'])) ? "ALL" : $sudo_commands['cmdlist']; $commands = ($commands == "all") ? "ALL" : $commands; $sudoers .= "{$user} ALL=({$runas}) {$nopasswd} {$commands}\n"; } /* Check validity of the sudoers data created above. */ $tmpsudoers = tempnam("/tmp", "sudoers"); file_put_contents($tmpsudoers, $sudoers); $result = exec("/usr/local/sbin/visudo -c -f {$tmpsudoers}"); /* If the file is OK, move it into place with the correct permissions, otherwise log an error and trash it. */ if (stristr($result, "parsed OK")) { rename($tmpsudoers, SUDO_SUDOERS); chmod(SUDO_SUDOERS, 0440); } else { log_error("Sudoers file invalid: {$result}"); unlink($tmpsudoers); } conf_mount_ro(); } /* Get a list of users and groups in a format we can use to make proper sudoers entries. Optionally include "ALL" as a user (for use by the Run As list) */ function sudo_get_users($list_all_user = false) { global $config; if (!is_array($config['system']['user'])) { $config['system']['user'] = array(); } $a_user = &$config['system']['user']; if (!is_array($config['system']['group'])) { $config['system']['group'] = array(); } $a_group = &$config['system']['group']; $users = array(); /* Make an entry for root, even though admin is essentially the same as root, they are distinct. */ $tmpuser = array(); $tmpuser["name"] = "user:root"; $tmpuser["descr"] = "User: root"; $users[] = $tmpuser; /* Add the all user if we want it */ if ($list_all_user) { $tmpuser = array(); $tmpuser["name"] = "user:ALL"; $tmpuser["descr"] = "User: ALL Users"; $users[] = $tmpuser; } foreach ($a_user as $user) { $tmpuser = array(); $tmpuser["name"] = "user:{$user['name']}"; $tmpuser["descr"] = "User: {$user['name']}"; $users[] = $tmpuser; } /* Add the wheel group here. We may need other manual groups later (e.g. operator) */ $tmpuser = array(); $tmpuser["name"] = "group:wheel"; $tmpuser["descr"] = "Group: wheel"; $users[] = $tmpuser; foreach ($a_group as $group) { /* The "all" group is internal and doesn't make sense to use here. */ if ($group['name'] == "all") { continue; } $tmpgroup = array(); $tmpgroup["name"] = "group:{$group['name']}"; $tmpgroup["descr"] = "Group: {$group['name']}"; $users[] = $tmpgroup; } return $users; } /* Make sure commands passed in are valid executables to help ensure a valid sudoers file and expected behavior. This also forces the user to give full paths to executables, which they should be doing anyhow. */ function sudo_validate_commands(&$input_errors) { $idx = 0; while (isset($_POST["cmdlist{$idx}"])) { $commands = $_POST["cmdlist" . $idx++]; if (strtoupper($commands) == "ALL") { continue; } $commands = explode(",", $commands); foreach ($commands as $command) { list($cmd, $params) = explode(" ", trim($command), 2); if (!is_executable($cmd)) { $input_errors[] = htmlspecialchars($cmd) . " is not an executable command."; } } } } ?>