#!/usr/bin/php * Copyright 2001-2010 Strangecode, LLC * * This file is part of The Strangecode Codebase. * * The Strangecode Codebase is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your option) * any later version. * * The Strangecode Codebase is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * The Strangecode Codebase. If not, see . */ /* * acl.cli.php * * @author Quinn Comendant * @version 1.0 * @since 14 Jun 2006 23:10:45 */ /******************************************************************** * STARTUP ********************************************************************/ $this_script = basename($_SERVER['argv'][0]); // Give them a fighting chance. Show the help message. ;P if ($_SERVER['argc'] <= 1) { help(); } // Make sure necessary files exist. define('COMMON_BASE', realpath('.')); $db_quth_file = COMMON_BASE . '/global/db_auth.inc.php'; if (!file_exists($db_quth_file)) { die(sprintf("%s error: the current directory must be common site directory (i.e. the parent directory of the document root) AND the global/db_auth.inc.php file must exist.\n", $this_script)); } if (fileowner($db_quth_file) != getmyuid()) { die(sprintf("%s error: you must execute this script as the owner of the web files.\n", $this_script)); } // Set include path. ini_set('include_path', get_include_path() . PATH_SEPARATOR . COMMON_BASE ); /******************************************************************** * CONFIG ********************************************************************/ // Include core libraries. require_once 'codebase/lib/App.inc.php'; require_once 'codebase/lib/Utilities.inc.php'; $app =& App::getInstance('module_maker'); $app->setParam(array( 'site_name' => 'ACL cli', 'site_email' => 'codebase@strangecode.com', 'enable_session' => false, 'enable_db' => true, 'db_always_debug' => false, 'db_debug' => true, 'db_die_on_failure' => true, 'display_errors' => true, 'error_reporting' => E_ALL, 'log_file_priority' => LOG_INFO, 'log_screen_priority' => LOG_ERR, 'log_directory' => COMMON_BASE . '/log', 'log_filename' => 'site_log', )); require_once 'global/db_auth.inc.php'; // Start application-based functionality: database, session, environment, ini setup, etc. // Most configuration parameters must be set before starting the App. $app->start(); // Global DB object. Automatically pre-configured by $app->start(). $db =& DB::getInstance(); // ACL! require_once 'codebase/lib/ACL.inc.php'; $acl =& ACL::getInstance(); $acl->setParam(array('create_table' => false)); /******************************************************************** * MAIN ********************************************************************/ $op = $_SERVER['argv'][1]; switch ($op) { case 'list' : $type = isset($_SERVER['argv'][2]) ? $_SERVER['argv'][2] : null; switch ($type) { case 'aro' : case 'aco' : case 'axo' : listObjects('root', $type); break; case 'all' : listObjects('root', 'aro'); listObjects('root', 'aco'); listObjects('root', 'axo'); break; case 'perms' : default : listPerms(); break; } break; case 'addaro' : case 'addaco' : case 'addaxo' : $object = isset($_SERVER['argv'][2]) ? $_SERVER['argv'][2] : null; $parent = isset($_SERVER['argv'][3]) ? $_SERVER['argv'][3] : null; if (!isset($object)) { echo "'add*' commands require at least one argument. Try 'help' if you are lost.\n"; break; } echo $acl->add($object, $parent, str_replace('add', '', $op)) ? "Ok\n" : "Error!\n"; break; case 'mvaro' : case 'mvaco' : case 'mvaxo' : $object = isset($_SERVER['argv'][2]) ? $_SERVER['argv'][2] : null; $parent = isset($_SERVER['argv'][3]) ? $_SERVER['argv'][3] : null; if (!isset($object)) { echo "'mv*' commands require at least one argument. Try 'help' if you are lost.\n"; break; } echo $acl->move($object, $parent, str_replace('mv', '', $op)) ? "Ok\n" : "Error!\n"; break; case 'rmaro' : case 'rmaco' : case 'rmaxo' : $object = isset($_SERVER['argv'][2]) ? $_SERVER['argv'][2] : null; if (!isset($object)) { echo "'add*' commands require at least one argument. Try 'help' if you are lost.\n"; break; } echo $acl->remove($object, str_replace('rm', '', $op)) ? "Ok\n" : "Error!\n"; break; case 'initdb' : echo $acl->initDB(true) ? "Ok\n" : "Error!\n"; break; case 'grant' : $aro = isset($_SERVER['argv'][2]) ? $_SERVER['argv'][2] : null; $aco = isset($_SERVER['argv'][3]) ? $_SERVER['argv'][3] : null; $axo = isset($_SERVER['argv'][4]) ? $_SERVER['argv'][4] : null; if (!isset($aro)) { echo "'grant' command require at least one argument. Try 'help' if you are lost.\n"; break; } echo $acl->grant($aro, $aco, $axo) ? "Ok\n" : "Error!\n"; break; case 'revoke' : $aro = isset($_SERVER['argv'][2]) ? $_SERVER['argv'][2] : null; $aco = isset($_SERVER['argv'][3]) ? $_SERVER['argv'][3] : null; $axo = isset($_SERVER['argv'][4]) ? $_SERVER['argv'][4] : null; if (!isset($aro)) { echo "'revoke' command require at least one argument. Try 'help' if you are lost.\n"; break; } echo $acl->revoke($aro, $aco, $axo) ? "Ok\n" : "Error!\n"; break; case 'delete' : $aro = isset($_SERVER['argv'][2]) && 'null' != $_SERVER['argv'][2] ? $_SERVER['argv'][2] : null; $aco = isset($_SERVER['argv'][3]) && 'null' != $_SERVER['argv'][3] ? $_SERVER['argv'][3] : null; $axo = isset($_SERVER['argv'][4]) && 'null' != $_SERVER['argv'][4] ? $_SERVER['argv'][4] : null; if (!isset($_SERVER['argv'][2]) || !isset($_SERVER['argv'][3]) || !isset($_SERVER['argv'][4])) { echo "'delete' command require all three arguments to be specified. Try 'help' if you are lost.\n"; break; } echo $acl->delete($aro, $aco, $axo) ? "Ok\n" : "Error!\n"; break; case 'check' : $aro = isset($_SERVER['argv'][2]) ? $_SERVER['argv'][2] : null; $aco = isset($_SERVER['argv'][3]) ? $_SERVER['argv'][3] : null; $axo = isset($_SERVER['argv'][4]) ? $_SERVER['argv'][4] : null; if (!isset($aro)) { echo "'check' command require at least one argument. Try 'help' if you are lost.\n"; break; } echo $acl->check($aro, $aco, $axo) ? "allow\n" : "deny\n"; break; case 'help' : help(); break; default : echo "'$op' is not an understood command. Try 'help' if you are lost.\n"; break; } /******************************************************************** * FUNCTIONS ********************************************************************/ function help() { global $this_script; ?> Access Control List command line tool. This script must be run in the common site directory (i.e. the parent directory of the document root). DB credentials are retrieved from: global/db_auth.inc.php so this file must exist. Further more this script must be executed as the owner of the db_auth.inc.php file. Three types of objects are managed by this interface: ARO - Access Request Objects, ACO - Access Control Objects, and AXO - Access Xtra Objects. These are most often used as a USER -> ACTION -> OBJECT model, but can just as easily be SPICES -> CUISINES -> DISHES A privilege is allowed if a user (ARO) can perform an action (ACO) on something (AXO). For example, Bob can edit article 4. If the AXO if omitted, this becomes "Bob can edit" (period). Each access object is stored as a node in hierarchical tree structures. A permission granted to a node is applied to all its children. If a child node is specified a different permission that is more specific that anything on the branch it will take precedence. If no permission is specified, root is used for that object. Root, in this case, means "anything" since it is at the top of all branches. Usage: command [args] Where command is any of the following (with arguments): initdb list [aro | aco | axo | all | perms] check aro [aco] [axo] addaro aro [parent] addaco aco [parent] addaxo axo [parent] mvaro aro [parent] mvaco aco [parent] mvaxo axo [parent] rmaro aro rmaco aco rmaxo axo grant aro [aco] [axo] revoke aro [aco] [axo] delete [aro] [aco] [axo] For the add*, mv*, grant, and revoke commands if any of the optional args are not provided, 'root' is assumed. For the delete command 'null' is considered a wild-card to delete all objects of that type. Strangecode :: www.strangecode.com * @version 1.0 * @since 17 Jun 2006 23:41:22 */ function listObjects($root, $type) { $app =& App::getInstance(); $db =& DB::getInstance(); global $this_script; echo "\n"; switch ($type) { case 'aro' : $tbl = 'aro_tbl'; printf("%-35s %-5s %-5s %s\n", 'Request objects', 'lft', 'rgt', 'Added'); break; case 'aco' : $tbl = 'aco_tbl'; printf("%-35s %-5s %-5s %s\n", 'Control objects', 'lft', 'rgt', 'Added'); break; case 'axo' : $tbl = 'axo_tbl'; printf("%-35s %-5s %-5s %s\n", 'Xtra objects', 'lft', 'rgt', 'Added'); break; default : $app->logMsg(sprintf('Invalid access object type: %s', $type), LOG_ERR, __FILE__, __LINE__); return false; break; } echo "-----------------------------------------------------------\n"; // Retrieve the left and right value of the $root node. $qid = $db->query("SELECT lft, rgt FROM $tbl WHERE name = '" . $db->escapeString($root) . "'"); list($lft, $rgt) = mysql_fetch_row($qid); $depth = array(); // Retrieve all descendants of the root node $qid = $db->query("SELECT name, lft, rgt, added_datetime FROM $tbl WHERE lft BETWEEN $lft AND $rgt ORDER BY lft ASC"); while (list($name, $lft, $rgt, $added_datetime) = mysql_fetch_row($qid)) { // If the last element of $depth is less than the current rgt it means we finished with a set of children nodes. while (sizeof($depth) > 0 && end($depth) < $rgt) { array_pop($depth); } // Display indented node title. printf("%-35s %-5s %-5s %s\n", str_repeat(' ', sizeof($depth)) . $name, $lft, $rgt, date($app->getParam('date_format'), strtotime($added_datetime))); // Add this node to the stack. $depth[] = $rgt; } } /* * List all entries in the acl_tbl. * * @access public * @author Quinn Comendant * @version 1.0 * @since 17 Jun 2006 15:11:53 */ function listPerms() { $app =& App::getInstance(); $db =& DB::getInstance(); global $this_script; // Retrieve access value from db. $qid = $db->query(" SELECT aro_tbl.name AS aro, aco_tbl.name AS aco, axo_tbl.name AS axo, acl_tbl.access, acl_tbl.added_datetime FROM acl_tbl LEFT JOIN aro_tbl ON (acl_tbl.aro_id = aro_tbl.aro_id) LEFT JOIN aco_tbl ON (acl_tbl.aco_id = aco_tbl.aco_id) LEFT JOIN axo_tbl ON (acl_tbl.axo_id = axo_tbl.axo_id) ORDER BY aro_tbl.lft ASC, aco_tbl.lft ASC, axo_tbl.lft ASC "); echo "\n"; printf("%-25s %-25s %-25s %-6s %-10s\n", 'Request objects', 'Control objects', 'Xtra objects', '', 'Added'); echo "------------------------------------------------------------------------------------------------\n"; while ($p = mysql_fetch_assoc($qid)) { printf("%-25s %-25s %-25s \033[0;%sm%-6s\033[0m %-10s\n", $p['aro'], $p['aco'], $p['axo'], ('allow' == $p['access'] ? '32' : '31'), $p['access'], date($app->getParam('date_format'), strtotime($p['added_datetime']))); } } ?>