From 3b4bb7749997b790801d2d795f2a523fc4bcb8bd Mon Sep 17 00:00:00 2001 From: chriskl Date: Sun, 9 Feb 2003 09:23:37 +0000 Subject: [PATCH] basic privilege viewing for databases and tables. more to follow --- classes/Misc.php | 6 +- classes/database/Postgres.php | 141 ++++++++- classes/database/Postgres72.php | 44 +-- conf/config.inc.php-dist | 17 +- display.php | 4 +- privileges.php | 488 +++----------------------------- 6 files changed, 189 insertions(+), 511 deletions(-) diff --git a/classes/Misc.php b/classes/Misc.php index 3b29d892..7bb953ed 100644 --- a/classes/Misc.php +++ b/classes/Misc.php @@ -2,7 +2,7 @@ /** * Class to hold various commonly used functions * - * $Id: Misc.php,v 1.12 2003/01/27 14:09:51 chriskl Exp $ + * $Id: Misc.php,v 1.13 2003/02/09 09:23:39 chriskl Exp $ */ class Misc { @@ -129,7 +129,7 @@ echo "{$strConstraints}\n"; echo "{$strTriggers}\n"; echo "{$strRules}\n"; - echo "{$strPrivileges}\n"; + echo "{$strPrivileges}\n"; echo "{$strExport}\n"; echo "\n"; } @@ -144,7 +144,7 @@ echo "\n"; echo "\n"; - echo "\n"; + echo "\n"; echo "\n"; echo "\n"; echo "
{$strSchemas}{$strPrivileges}{$strPrivileges}{$strSQL}{$strExport}
\n"; diff --git a/classes/database/Postgres.php b/classes/database/Postgres.php index 71abd7c6..ad2f7860 100755 --- a/classes/database/Postgres.php +++ b/classes/database/Postgres.php @@ -4,7 +4,7 @@ * A class that implements the DB interface for Postgres * Note: This class uses ADODB and returns RecordSets. * - * $Id: Postgres.php,v 1.49 2003/01/27 06:08:35 chriskl Exp $ + * $Id: Postgres.php,v 1.50 2003/02/09 09:23:39 chriskl Exp $ */ // @@@ THOUGHT: What about inherits? ie. use of ONLY??? @@ -61,6 +61,34 @@ class Postgres extends BaseDB { 'LATIN10' => 'ISO-8859-16', 'UNICODE' => 'UTF-8' ); + + // List of all legal privileges that can be applied to different types + // of objects. + var $privlist = array( + 'table' => array('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', 'TRIGGER', 'ALL PRIVILEGES'), + 'view' => array('SELECT', 'RULE', 'ALL PRIVILEGES'), + 'sequence' => array('SELECT', 'UPDATE', 'ALL PRIVILEGES'), + 'database' => array('CREATE', 'TEMPORARY', 'ALL PRIVILEGES'), + 'function' => array('EXECUTE', 'ALL PRIVILEGES'), + 'language' => array('USAGE', 'ALL PRIVILEGES'), + 'schema' => array('CREATE', 'USAGE', 'ALL PRIVILEGES') + ); + + // List of characters in acl lists and the privileges they + // refer to. + var $privmap = array( + 'r' => 'SELECT', + 'w' => 'UPDATE', + 'a' => 'INSERT', + 'd' => 'DELETE', + 'R' => 'RULE', + 'x' => 'REFERENCES', + 't' => 'TRIGGER', + 'X' => 'EXECUTE', + 'U' => 'USAGE', + 'C' => 'CREATE', + 'T' => 'TEMPORARY' + ); function Postgres($host, $port, $database, $user, $password) { $this->BaseDB('postgres7'); @@ -309,6 +337,17 @@ class Postgres extends BaseDB { $sql = "DROP DATABASE \"{$database}\""; return $this->execute($sql); } + + /** + * Dumps a database + */ + function dbDump($database) { + global $appDumper; + + $database = escapeshellarg($database); + + passthru("/usr/local/bin/pg_dump {$database}"); + } // Table functions @@ -1464,6 +1503,106 @@ class Postgres extends BaseDB { return $this->execute($sql); } + // Privilege functions + + /** + * Grabs an array of users and their privileges for an object, + * given its type. + * @param $object The name of the object whose privileges are to be retrieved + * @param $type The type of the object (eg. database, schema, relation, function or language + * @return Privileges array + * @return -1 invalid type + * @return -2 object not found + * @return -3 unknown privilege type + */ + function getPrivileges($object, $type) { + $this->clean($object); + + // @@ NEED SCHEMA SUPPORT FOR 7.3 + switch ($type) { + case 'table': + case 'view': + case 'sequence': + $sql = "SELECT relacl AS acl FROM pg_class WHERE relname = '{$object}'"; + break; + case 'database': + $sql = "SELECT datacl AS acl FROM pg_database WHERE datname = '{$object}'"; + break; + case 'function': + $sql = "SELECT proacl AS acl FROM pg_proc WHERE proname = '{$object}'"; + break; + case 'language': + $sql = "SELECT lanacl AS acl FROM pg_language WHERE lanname = '{$object}'"; + break; + case 'schema': + // @@ MOVE THIS TO 7.3 ONLY + $sql = "SELECT nspacl AS acl FROM pg_namespace WHERE nspname = '{$object}'"; + break; + default: + return -1; + } + + // Fetch the ACL for object + $acl = $this->selectField($sql, 'acl'); + if ($acl == -1) return -2; + elseif ($acl == '') return array(); + + // Take off the first and last characters (the braces) + $acl = substr($acl, 1, strlen($acl) - 2); + + // Pick out individual ACE's by exploding on the comma + $aces = explode(',', $acl); + + // Create the array to be returned + $temp = array(); + + // For each ACE, generate an entry in $temp + foreach ($aces as $v) { + // If the ACE begins with a double quote, strip them off both ends + if (strpos($v, '"') === 0) $v = substr($v, 1, strlen($v) - 2); + + // Figure out type of ACE (public, user or group) + if (strpos($v, '=') === 0) + $atype = 'public'; + elseif (strpos($v, 'group ') === 0) { + $atype = 'group'; + // Tear off 'group' prefix + $v = substr($v, 6); + } + else + $atype = 'user'; + + // Separate entity from character list + list ($entity, $chars) = explode('=', $v); + + // New row to be added to $temp + // (type, grantee, privilegs, grantor, grant option + $row = array($atype, $entity, array(), '', false); + + // Loop over chars and add privs to $row + for ($i = 0; $i < strlen($chars); $i++) { + // Append to row's privs list the string representing + // the privilege + $char = substr($chars, $i, 1); + if ($char == '*') + $row[4] = true; + elseif ($char == '/') { + $row[5] = substr($chars, $i + 1); + break; + } + if (!isset($this->privmap[$char])) + return -3; + else + $row[2][] = $this->privmap[$char]; + } + + // Append row to temp + $temp[] = $row; + } + + return $temp; + } + // Capabilities function hasTables() { return true; } function hasViews() { return true; } diff --git a/classes/database/Postgres72.php b/classes/database/Postgres72.php index 6a70e712..36da59c4 100644 --- a/classes/database/Postgres72.php +++ b/classes/database/Postgres72.php @@ -4,7 +4,7 @@ * A class that implements the DB interface for Postgres * Note: This class uses ADODB and returns RecordSets. * - * $Id: Postgres72.php,v 1.25 2003/01/18 06:38:37 chriskl Exp $ + * $Id: Postgres72.php,v 1.26 2003/02/09 09:23:39 chriskl Exp $ */ @@ -334,48 +334,6 @@ class Postgres72 extends Postgres71 { return $this->selectSet($sql); } - /** - * Grabs a list of privileges for an object - * @param $object The object whose privileges are to be retrived - * @return array containing username and privileges - */ - - function getPrivileges($object = '') { - $this->clean($object); - - $sql = "SELECT relacl FROM pg_class WHERE relname = '$object'"; - - $acl = $this->selectField($sql, 'relacl'); - - $acldata = trim(ereg_replace("[\{\"]", "", $acl)); - - $users = explode(',',$acldata); - $numusers = count($users); - - // Hardcode in the field names we intend to use in our displays - // this needs to be converted to strings really - $privileges[0] = 'user/group@!@select@!@insert@!@update@!@delete@!@rule@!@references@!@trigger'; - - for ($i=0; $i<$numusers; $i++) - { - $userarray = explode("=", $users[$i]); - $username = $userarray[0] ? $userarray[0] : "public"; - $privlist = $userarray[1]; - - $privileges[$i+1] = $username; - - $pgAcl = array('r','a','w','d','R','x','t'); - for ($n = 0; $n < 7; $n++) - { - $privileges[$i+1] .= strchr($privlist, $pgAcl[$n]) ? '@!@Yes' : '@!@No'; - } - - } - - return $privileges; - } - - } ?> diff --git a/conf/config.inc.php-dist b/conf/config.inc.php-dist index 422546fe..cf38f46b 100644 --- a/conf/config.inc.php-dist +++ b/conf/config.inc.php-dist @@ -4,7 +4,7 @@ * Central WebDB configuration. As a user you may modify the * settings here for your particular configuration. * - * $Id: config.inc.php-dist,v 1.10 2003/02/07 17:34:36 xzilla Exp $ + * $Id: config.inc.php-dist,v 1.11 2003/02/09 09:23:40 chriskl Exp $ */ // Set error reporting level @@ -12,7 +12,10 @@ // Default language setting. eg 'english', 'polish', etc. $appDefaultLanguage = 'english'; - + + // Name for reports database + $appReportsDB = 'phppgadmin'; + /* * GUI settings */ @@ -36,11 +39,11 @@ $confServers[0]['default'] = 'template1'; // Servers and types - $confServers[1]['desc'] = 'Development'; - $confServers[1]['host'] = 'database-dev'; - $confServers[1]['port'] = 5432; - $confServers[1]['type'] = 'Postgres73'; - $confServers[1]['default'] = 'template1'; + //$confServers[1]['desc'] = 'Development'; + //$confServers[1]['host'] = 'database-dev'; + //$confServers[1]['port'] = 5432; + //$confServers[1]['type'] = 'Postgres73'; + //$confServers[1]['default'] = 'template1'; /***************************************** * Don't modify anything below this line * diff --git a/display.php b/display.php index df2e9560..1dad153e 100644 --- a/display.php +++ b/display.php @@ -9,7 +9,7 @@ * @param $return_desc The return link name * @param $page The current page * - * $Id: display.php,v 1.4 2003/02/07 17:34:34 xzilla Exp $ + * $Id: display.php,v 1.5 2003/02/09 09:23:37 chriskl Exp $ */ // Include application functions @@ -43,7 +43,7 @@ echo "\n"; reset($rs->f); while(list($k, ) = each($rs->f)) { - echo ""; } $i = 0; diff --git a/privileges.php b/privileges.php index a92bee94..a32e294c 100644 --- a/privileges.php +++ b/privileges.php @@ -1,9 +1,9 @@ setView($_POST['view'], $_POST['formDefinition']); - if ($status == 0) - doProperties('View updated.'); - else - doEdit('View update failed.'); - } - - /** - * Function to allow editing of a view - */ - function doEdit($msg = '') { - global $data, $localData, $misc; - global $PHP_SELF, $strName, $strDefinition; - - echo "

", htmlspecialchars($_REQUEST['database']), ": Views: ", htmlspecialchars($_REQUEST['view']), ": Edit

\n"; - $misc->printMsg($msg); - - $viewdata = &$localData->getView($_REQUEST['view']); - - if ($viewdata->recordCount() > 0) { - echo "\n"; - echo "
", htmlspecialchars($k), ""; + echo "", htmlspecialchars($k), "
\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "
{$strName}
", htmlspecialchars($viewdata->f[$data->vwFields['vwname']]), "
{$strDefinition}
\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo " \n"; - echo "\n"; - } - else echo "

No data.

\n"; - - echo "

Show All Views |\n"; - echo "Properties

\n"; - } - - /** - * Show read only properties for a view - */ - function doProperties($msg = '') { - global $data, $localData, $misc; - global $PHP_SELF, $strName, $strDefinition; - - echo "

", htmlspecialchars($_REQUEST['database']), ": Views: ", htmlspecialchars($_REQUEST['view']), ": Properties

\n"; - $misc->printMsg($msg); - - $viewdata = &$localData->getView($_REQUEST['view']); - - if ($viewdata->recordCount() > 0) { - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "
{$strName}
", htmlspecialchars($viewdata->f[$data->vwFields['vwname']]), "
{$strDefinition}
", nl2br(htmlspecialchars($viewdata->f[$data->vwFields['vwdef']])), "
\n"; - } - else echo "

No data.

\n"; - - echo "

Show All Views |\n"; - echo "Edit

\n"; - } - - /** - * Show confirmation of drop and perform actual drop - */ - function doDrop($confirm) { - global $localData, $database; - global $PHP_SELF; - if ($confirm) { - echo "

", htmlspecialchars($_REQUEST['database']), ": Views: ", htmlspecialchars($_REQUEST['view']), ": Drop

\n"; - - echo "

Are you sure you want to drop the view \"", htmlspecialchars($_REQUEST['view']), "\"?

\n"; - - echo "
\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo " \n"; - echo "
\n"; - } - else { - $status = $localData->dropView($_POST['view']); - if ($status == 0) - doDefault('View dropped.'); - else - doDefault('View drop failed.'); - } - - } - - /** - * Displays a screen where they can enter a new view - */ - function doCreate($msg = '') { - global $data, $localData, $misc; - global $PHP_SELF, $strName, $strDefinition; - - if (!isset($_POST['formView'])) $_POST['formView'] = ''; - if (!isset($_POST['formDefinition'])) $_POST['formDefinition'] = ''; - - echo "

", htmlspecialchars($_REQUEST['database']), ": Views: Create View

\n"; - $misc->printMsg($msg); - - echo "
\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "
{$strName}
_maxNameLen} maxlength={$data->_maxNameLen} value=\"", - htmlspecialchars($_POST['formView']), "\">
{$strDefinition}
\n"; - echo "\n"; - echo "\n"; - echo " \n"; - echo "
\n"; - - echo "

Show All Views

\n"; - } - /** - * Actually creates the new view in the database + * Show permissions on a database, namespace, relation, language or function */ - function doSaveCreate() { - global $localData, $strViewNeedsName, $strViewNeedsDef; - - // Check that they've given a name and a definition - if ($_POST['formView'] == '') doCreate($strViewNeedsName); - elseif ($_POST['formDefinition'] == '') doCreate($strViewNeedsDef); - else { - $status = $localData->createView($_POST['formView'], $_POST['formDefinition']); - if ($status == 0) - doDefault('View created.'); - else - doCreate('View creation failed.'); - } -/* - $i = 0; - while ($p = $arrPrivileges[$i]) { - $cb_priv[$p] = ' ". ucfirst($p) .""; - $i++; - } - $Expected = $strYes; - $Action = "grant"; - $strToFrom = "to"; - - $privileges = get_privilege($table); - switch ($action) { - case "revoke": - $Expected = $strNo; - $Action = "revoke"; - $strToFrom = "from"; - case "grant": - $name = rawurldecode($user); - - $i = 0; - while ($p = $arrPrivileges[$i]) { - if ($privileges[$name][$p] == $Expected) { - unset($cb_priv[$p]); } - $i++; - } - $user = "$cfgQuotes$name$cfgQuotes"; - $user = eregi_replace("${cfgQuotes}group ", "GROUP $cfgQuotes", $user); - $user = eregi_replace("${cfgQuotes}public$cfgQuotes", "PUBLIC", $user); - $input_user = ''; - break; - case "grantuser": - $qrUsers = "SELECT 'public'::text AS thename UNION SELECT '$cfgQuotes' || usename || '$cfgQuotes' AS thename FROM pg_user WHERE usename NOT IN ('root', '$cfgSuperUser'"; - @reset($privileges); - while (list($key) = @each ($privileges)) - if (!ereg("group ", $key)) - $qrUsers .= ", '$key'"; - $qrUsers .= ") ORDER BY thename"; - case "grantgroup": - if (!isset($qrUsers)) { - $qrUsers = "SELECT 'group $cfgQuotes' || groname || '$cfgQuotes' AS thename FROM pg_group"; - @reset($privileges); - while (list($key) = @each($privileges)) - if (ereg("^group (.+)$", $key, $regs)) - $tmp .=", '".$regs[1]."'"; - - if (isset($tmp)) { - $tmp[0] = '('; - $qrUsers .= " WHERE groname NOT IN $tmp)"; - } - $qrUsers .= " ORDER BY thename"; - } - if (!$res = @pg_exec($link, $qrUsers)) { - pg_die(pg_errormessage($link), $qrUsers, __FILE__, __LINE__); - } else { - $name = '\n"; - } - } - unset($action); -*/ - - - } - - /** - * Show the grant menu on the screen - */ - - function doModify($action) { + function doDefault($msg = '') { global $data, $localData, $misc, $database; - global $PHP_SELF, $strPrivileges, $strGrant, $strRevoke, $strCancel; - global $strUser,$strGroup,$strSelect,$strInsert,$strUpdate,$strDelete,$strRule; - global $strReferences,$strTrigger,$strAction,$strYes,$strNo; - - $object = $_REQUEST['object']; - // $server = $_REQUEST['server']; - $server = 'deprecated'; - $user = $_REQUEST['user']; - $db = $_REQUEST['database']; - - $arrPrivileges = array('select', 'insert', 'update', 'delete', 'rule', 'references', 'trigger'); - $arrAcl = array('r', 'a', 'w', 'd', 'R', 'x', 't'); - - $i = 0; - while ($p = $arrPrivileges[$i]) { - $cb_priv[$p] = ' ". ucfirst($p) .""; - $i++; - } - - // $privileges = get_privilege($table); - $privileges = &$localData->getPrivileges($object); - - $GrantRevoke = $strGrant; - $ToFrom = 'to'; - $Expected = $strYes; + global $PHP_SELF, $strPrivileges, $strGrant, $strRevoke; + global $strUser, $strGroup, $strSelect, $strInsert, $strUpdate, $strDelete, $strRule; + global $strReferences, $strTrigger, $strAction, $strYes, $strNo, $strType; - switch ($action) { - case "revoke": - $GrantRevoke = $strRevoke; - $ToFrom = 'from'; - $Expected = $strNo; - case "grant": - - $name = rawurldecode($user); - - $i = 0; - while ($p = $arrPrivileges[$i]) { - echo $privileges[$name][$p]; - if ($privileges[$name][$p] == $Expected) { - unset($cb_priv[$p]); } - $i++; - } - $user = "\"$name\""; - $user = eregi_replace("group", "GROUP", $user); - $user = eregi_replace("public", "PUBLIC", $user); - $input_user = ''; + switch ($_REQUEST['type']) { + case 'database': + $misc->printDatabaseNav(); + break; + case 'table': + $misc->printTableNav(); break; - case "grantuser": - $qrUsers = "SELECT 'public'::text AS thename UNION SELECT '$cfgQuotes' || usename || '$cfgQuotes' AS thename FROM pg_user WHERE usename NOT IN ('root', '$cfgSuperUser'"; - @reset($privileges); - while (list($key) = @each ($privileges)) - if (!ereg("group ", $key)) - $qrUsers .= ", '$key'"; - $qrUsers .= ") ORDER BY thename"; - case "grantgroup": - if (!isset($qrUsers)) { - $qrUsers = "SELECT 'group $cfgQuotes' || groname || '$cfgQuotes' AS thename FROM pg_group"; - @reset($privileges); - while (list($key) = @each($privileges)) - if (ereg("^group (.+)$", $key, $regs)) - $tmp .=", '".$regs[1]."'"; - if (isset($tmp)) { - $tmp[0] = '('; - $qrUsers .= " WHERE groname NOT IN $tmp)"; - } - $qrUsers .= " ORDER BY thename"; - } - if (!$res = @pg_exec($link, $qrUsers)) { - pg_die(pg_errormessage($link), $qrUsers, __FILE__, __LINE__); - } else { - $name = '\n"; - } - } - unset($action); - - echo "

", htmlspecialchars($db), ": $strPrivileges : $object : $GrantRevoke

\n"; - - echo strtoupper($GrantRevoke); - - echo '
'; - - $i = 0; - while ($p = $arrPrivileges[$i]) { - if (isset($cb_priv[$p])) { - echo $cb_priv[$p], "
"; - } - $i++; - } - - echo "ON $object ". strtoupper($ToFrom) ." $name"; - - echo '\n"; - echo '\n"; - echo '\n"; - echo $input_user; - echo '

'; - echo '\n"; - echo ''; - echo '

'; - - - -/* - $privs = &$localData->getPrivileges($object); - - if ($privs->recordCount() == 1) { - - $i = 0; - while ($p = $privs[$i]) { - $cb_priv[$p] = ' ". ucfirst($p) .""; - $i++; - } - $Expected = $strYes; - $strToFrom = "to"; - - - $name = rawurldecode($_REQUEST['user']); - - $i = 0; - while ($p = $privs[$i]) { - if ($privs[$name][$p] == $Expected) { - unset($cb_priv[$p]); } - $i++; - } - $user = "$name"; - $user = eregi_replace(" ", "GROUP", $user); - $user = eregi_replace(" ", "PUBLIC", $user); - $input_user = ''; - } - - echo '
'; - - $i = 0; - while ($p = $arrPrivileges[$i]) { - if (isset($cb_priv[$p])) { - echo $cb_priv[$p], "
"; - } - $i++; } - -*/ - } - - - /** - * Show default list of views in the database - */ - function doDefault($msg = '') { - global $data, $localData, $misc, $database; - global $PHP_SELF, $strPrivileges, $strGrant, $strRevoke; - global $strUser,$strGroup,$strSelect,$strInsert,$strUpdate,$strDelete,$strRule; - global $strReferences,$strTrigger,$strAction,$strYes,$strNo; - - - // the intention here is to look for an 'object' in the request array, and if found - // use it, if not found, use table. unfortunatly this throws an error (though it works) - - $object = $_REQUEST['object'] ? $_REQUEST['object'] : $_REQUEST['table']; - - echo "

", htmlspecialchars($_REQUEST['database']), ": $strPrivileges : $object

\n"; + echo "

$strPrivileges: ", htmlspecialchars($_REQUEST['object']), "

\n"; $misc->printMsg($msg); - $privileges = &$localData->getPrivileges($object); - - // We must return only one row from the above query + // Get the privileges on the object, given its type + $privileges = $localData->getPrivileges($_REQUEST['object'], $_REQUEST['type']); echo "\n"; + echo ""; + echo "\n"; - $i = 1; - for ($y=0;$y\n"; + echo "\n"; + echo "\n"; + foreach ($data->privlist[$_REQUEST['type']] as $v2) { + if (in_array($v2, $v[2])) + echo "\n"; + else + echo "\n"; } - - echo ""; - - for ($x=0;$x$strGrant" . $ctf . $otf ."$strRevoke" . $ctf; - - if ($y==0) { - $endcap = "\n"; + echo "\n"; echo "\n"; $i++; } - echo '
{$strType}User/Group", + join('', $data->privlist[$_REQUEST['type']]), "Grant Option?Grantor
", htmlspecialchars($v[0]), "", htmlspecialchars($v[1]), "$strYes$strNo
$strAction"; - } - - echo $endcap; + echo "", ($v[3]) ? $strYes : $strNo, "", htmlspecialchars($v[4]), "
'; - - - //} else { - // echo "Could Not Retrieve ACL for Object $object"; - //} - + echo ""; } $misc->printHeader($strPrivileges); switch ($action) { - case 'save_create': - doSaveCreate(); - break; - case 'create': - doCreate(); - break; - case 'drop': - if ($_POST['choice'] == 'Yes') doDrop(false); - else doDefault(); - break; - case 'confirm_drop': - doDrop(true); - break; - case 'save_edit': - doSaveEdit(); - break; case 'edit': doEdit(); break; - case 'properties': - doProperties(); - break; - case 'grant': - doModify('grant'); - break; - case 'revoke': - doModify('revoke'); - break; default: doDefault(); break; -- 2.39.5