bug #1307208, detect lack of permission for CREATE TABLE

This commit is contained in:
Marc Delisle
2005-09-30 19:22:11 +00:00
parent ea707775d2
commit 863a6e24d4
7 changed files with 119 additions and 86 deletions

View File

@@ -5,6 +5,13 @@ phpMyAdmin - Changelog
$Id$ $Id$
$Source$ $Source$
2005-09-30 Marc Delisle <lem9@users.sourceforge.net>
* main.php, db_details_structure.php, db_operations.php,
libraries/check_user_privileges.php, /display_create_database.lib.php,
/display_create_table.lib.php: bug #1307208, detect lack of privileges
before showing the "Create new table" dialog. Please test.
TODO: detect escaped wildcard privileges
2005-09-30 Michal Čihař <michal@cihar.com> 2005-09-30 Michal Čihař <michal@cihar.com>
* libraries/display_export.lib.php, libraries/export/sql.php, * libraries/display_export.lib.php, libraries/export/sql.php,
db_operations.php, tbl_properties_operations.php: Fix auto increment db_operations.php, tbl_properties_operations.php: Fix auto increment

View File

@@ -632,41 +632,7 @@ if ($num_tables > 0) {
} // end if } // end if
if (PMA_MYSQL_INT_VERSION < 50002 || (PMA_MYSQL_INT_VERSION >= 50002 && $db != 'information_schema')) { if (PMA_MYSQL_INT_VERSION < 50002 || (PMA_MYSQL_INT_VERSION >= 50002 && $db != 'information_schema')) {
?> require('./libraries/display_create_table.lib.php');
<!-- Create a new table -->
<form method="post" action="tbl_create.php" onsubmit="return (emptyFormElements(this, 'table') && checkFormElementInRange(this, 'num_fields', '<?php echo str_replace('\'', '\\\'', $GLOBALS['strInvalidFieldCount']); ?>', 1))">
<table border="0" cellpadding="2" cellspacing="0">
<tr>
<td class="tblHeaders" colspan="3" nowrap="nowrap"><?php
echo PMA_generate_common_hidden_inputs($db);
if($cfg['PropertiesIconic']){ echo '<img src="' . $pmaThemeImage . 'b_newtbl.png" border="0" width="16" height="16" hspace="2" align="middle" />'; }
// if you want navigation:
$strDBLink = '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url() . '&amp;db=' . urlencode($GLOBALS['db']) . '">'
. htmlspecialchars($GLOBALS['db']) . '</a>';
// else use
// $strDBLink = htmlspecialchars($db);
echo ' ' . sprintf($strCreateNewTable, $strDBLink) . ':&nbsp;' . "\n";
echo ' </td></tr>';
echo ' <tr bgcolor="'.$cfg['BgcolorOne'].'"><td nowrap="nowrap">';
echo ' ' . $strName . ':&nbsp;' . "\n";
echo ' </td>';
echo ' <td nowrap="nowrap">';
echo ' ' . '<input type="text" name="table" maxlength="64" size="30" class="textfield" />';
echo ' </td><td>&nbsp;</td></tr>';
echo ' <tr bgcolor="'.$cfg['BgcolorOne'].'"><td nowrap="nowrap">';
if (!isset($strNumberOfFields)) {
$strNumberOfFields = $strFields;
}
echo ' ' . $strNumberOfFields . ':&nbsp;' . "\n";
echo ' </td>';
echo ' <td nowrap="nowrap">';
echo ' ' . '<input type="text" name="num_fields" size="2" class="textfield" />' . "\n";
echo ' </td>';
echo ' <td align="right">';
echo ' ' . '&nbsp;<input type="submit" value="' . $strGo . '" />' . "\n";
echo ' </td> </tr>';
echo ' </table>';
echo '</form>';
} // end if (Create Table dialog) } // end if (Create Table dialog)
/** /**

View File

@@ -141,39 +141,8 @@ if (PMA_MYSQL_INT_VERSION < 50002 || (PMA_MYSQL_INT_VERSION >= 50002 && $db != '
} }
if (!$is_information_schema) { if (!$is_information_schema) {
?>
<table border="0" cellpadding="2" cellspacing="0"> require('./libraries/display_create_table.lib.php');
<!-- Create a new table -->
<form method="post" action="tbl_create.php" onsubmit="return (emptyFormElements(this, 'table') && checkFormElementInRange(this, 'num_fields', '<?php echo str_replace('\'', '\\\'', $GLOBALS['strInvalidFieldCount']); ?>', 1))">
<tr>
<td class="tblHeaders" colspan="3" nowrap="nowrap"><?php
echo PMA_generate_common_hidden_inputs($db);
if($cfg['PropertiesIconic']){ echo '<img src="' . $pmaThemeImage . 'b_newtbl.png" border="0" width="16" height="16" hspace="2" align="middle" />'; }
// if you want navigation:
$strDBLink = '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url() . '&amp;db=' . urlencode($GLOBALS['db']) . '">'
. htmlspecialchars($GLOBALS['db']) . '</a>';
// else use
// $strDBLink = htmlspecialchars($db);
echo ' ' . sprintf($strCreateNewTable, $strDBLink) . ':&nbsp;' . "\n";
echo ' </td></tr>';
echo ' <tr bgcolor="'.$cfg['BgcolorOne'].'"><td nowrap="nowrap">';
echo ' ' . $strName . ':&nbsp;' . "\n";
echo ' </td>';
echo ' <td nowrap="nowrap">';
echo ' ' . '<input type="text" name="table" maxlength="64" size="30" class="textfield" />';
echo ' </td><td>&nbsp;</td></tr>';
echo ' <tr bgcolor="'.$cfg['BgcolorOne'].'"><td nowrap="nowrap">';
echo ' ' . $strFields . ':&nbsp;' . "\n";
echo ' </td>';
echo ' <td nowrap="nowrap">';
echo ' ' . '<input type="text" name="num_fields" size="2" class="textfield" />' . "\n";
echo ' </td>';
echo ' <td align="right">';
echo ' ' . '&nbsp;<input type="submit" value="' . $strGo . '" />' . "\n";
echo ' </td> </tr>' . "\n";
echo ' </form>' . "\n";
echo '</table>' . "\n";
echo '<table border="0" cellpadding="2" cellspacing="0">'; echo '<table border="0" cellpadding="2" cellspacing="0">';
if ($cfgRelation['commwork']) { if ($cfgRelation['commwork']) {

View File

@@ -2,21 +2,22 @@
/* $Id$ */ /* $Id$ */
// vim: expandtab sw=4 ts=4 sts=4: // vim: expandtab sw=4 ts=4 sts=4:
// Get user's global privileges ($dbh and $userlink are links to MySQL // Get user's global privileges and some db-specific privileges
// defined in the "common.lib.php" library) // ($dbh and $userlink are links to MySQL defined in the "common.lib.php" library)
// Note: if no controluser is defined, $dbh contains $userlink // Note: if no controluser is defined, $dbh contains $userlink
$is_create_priv = FALSE; $is_create_db_priv = FALSE;
$is_process_priv = TRUE; $is_process_priv = TRUE;
$is_reload_priv = FALSE; $is_reload_priv = FALSE;
$db_to_create = ''; $db_to_create = '';
$dbs_where_create_table_allowed = array();
// We were trying to find if user if superuser with 'USE mysql' // We were trying to find if user if superuser with 'USE mysql'
// but users with the global priv CREATE TEMPORARY TABLES or LOCK TABLES // but users with the global priv CREATE TEMPORARY TABLES or LOCK TABLES
// can do a 'USE mysql' (even if they cannot see the tables) // can do a 'USE mysql' (even if they cannot see the tables)
$is_superuser = PMA_DBI_try_query('SELECT COUNT(*) FROM mysql.user', $userlink, PMA_DBI_QUERY_STORE); $is_superuser = PMA_DBI_try_query('SELECT COUNT(*) FROM mysql.user', $userlink, PMA_DBI_QUERY_STORE);
function PMA_analyseShowGrant($rs_usr, &$is_create_priv, &$db_to_create, &$is_reload_priv) { function PMA_analyseShowGrant($rs_usr, &$is_create_db_priv, &$db_to_create, &$is_reload_priv, &$dbs_where_create_table_allowed) {
$re0 = '(^|(\\\\\\\\)+|[^\])'; // non-escaped wildcards $re0 = '(^|(\\\\\\\\)+|[^\])'; // non-escaped wildcards
$re1 = '(^|[^\])(\\\)+'; // escaped wildcards $re1 = '(^|[^\])(\\\)+'; // escaped wildcards
@@ -26,19 +27,32 @@ function PMA_analyseShowGrant($rs_usr, &$is_create_priv, &$db_to_create, &$is_re
$show_grants_str = substr($row[0],6,(strpos($row[0],' ON ')-6)); $show_grants_str = substr($row[0],6,(strpos($row[0],' ON ')-6));
if (($show_grants_str == 'ALL') || ($show_grants_str == 'ALL PRIVILEGES') || ($show_grants_str == 'CREATE') || strpos($show_grants_str, 'CREATE')) { if (($show_grants_str == 'ALL') || ($show_grants_str == 'ALL PRIVILEGES') || ($show_grants_str == 'CREATE') || strpos($show_grants_str, 'CREATE')) {
if ($show_grants_dbname == '*') { if ($show_grants_dbname == '*') {
$is_create_priv = TRUE; // a global CREATE privilege
$is_create_db_priv = TRUE;
$is_reload_priv = TRUE; $is_reload_priv = TRUE;
$db_to_create = ''; $db_to_create = '';
$dbs_where_create_table_allowed[] = '*';
break; break;
} // end if } // end if
else if ( (ereg($re0 . '%|_', $show_grants_dbname) else {
// this array may contain wildcards
$dbs_where_create_table_allowed[] = $show_grants_dbname;
if ( (ereg($re0 . '%|_', $show_grants_dbname)
&& !ereg('\\\\%|\\\\_', $show_grants_dbname)) && !ereg('\\\\%|\\\\_', $show_grants_dbname))
// does this db exist?
|| (!PMA_DBI_try_query('USE ' . ereg_replace($re1 .'(%|_)', '\\1\\3', $show_grants_dbname)) && substr(PMA_DBI_getError(), 1, 4) != 1044) || (!PMA_DBI_try_query('USE ' . ereg_replace($re1 .'(%|_)', '\\1\\3', $show_grants_dbname)) && substr(PMA_DBI_getError(), 1, 4) != 1044)
) { ) {
$db_to_create = ereg_replace($re0 . '%', '\\1...', ereg_replace($re0 . '_', '\\1?', $show_grants_dbname)); $db_to_create = ereg_replace($re0 . '%', '\\1...', ereg_replace($re0 . '_', '\\1?', $show_grants_dbname));
$db_to_create = ereg_replace($re1 . '(%|_)', '\\1\\3', $db_to_create); $db_to_create = ereg_replace($re1 . '(%|_)', '\\1\\3', $db_to_create);
$is_create_priv = TRUE; $is_create_db_priv = TRUE;
break;
// TODO: collect $db_to_create into an array, to display a drop-down
// in the "Create new database" dialog
//
// now we don't break, we want all possible databases
//break;
} // end if
} // end elseif } // end elseif
} // end if } // end if
} // end while } // end while
@@ -53,7 +67,7 @@ function PMA_analyseShowGrant($rs_usr, &$is_create_priv, &$db_to_create, &$is_re
if (PMA_MYSQL_INT_VERSION >= 40102) { if (PMA_MYSQL_INT_VERSION >= 40102) {
$rs_usr = PMA_DBI_try_query('SHOW GRANTS', $userlink, PMA_DBI_QUERY_STORE); $rs_usr = PMA_DBI_try_query('SHOW GRANTS', $userlink, PMA_DBI_QUERY_STORE);
if ($rs_usr) { if ($rs_usr) {
PMA_analyseShowGrant($rs_usr,$is_create_priv, $db_to_create, $is_reload_priv); PMA_analyseShowGrant($rs_usr,$is_create_db_priv, $db_to_create, $is_reload_priv, $dbs_where_create_table_allowed);
PMA_DBI_free_result($rs_usr); PMA_DBI_free_result($rs_usr);
unset($rs_usr); unset($rs_usr);
} }
@@ -63,7 +77,7 @@ if (PMA_MYSQL_INT_VERSION >= 40102) {
// the controluser is correctly defined; but here, $dbh could contain // the controluser is correctly defined; but here, $dbh could contain
// $userlink so maybe the SELECT will fail // $userlink so maybe the SELECT will fail
if (!$is_create_priv) { if (!$is_create_db_priv) {
$res = PMA_DBI_query('SELECT USER();'); $res = PMA_DBI_query('SELECT USER();');
list($mysql_cur_user_and_host) = PMA_DBI_fetch_row($res); list($mysql_cur_user_and_host) = PMA_DBI_fetch_row($res);
$mysql_cur_user = substr($mysql_cur_user_and_host, 0, strrpos($mysql_cur_user_and_host, '@')); $mysql_cur_user = substr($mysql_cur_user_and_host, 0, strrpos($mysql_cur_user_and_host, '@'));
@@ -72,8 +86,8 @@ if (PMA_MYSQL_INT_VERSION >= 40102) {
$rs_usr = PMA_DBI_try_query($local_query, $dbh); // Debug: or PMA_mysqlDie('', $local_query, FALSE); $rs_usr = PMA_DBI_try_query($local_query, $dbh); // Debug: or PMA_mysqlDie('', $local_query, FALSE);
if ($rs_usr) { if ($rs_usr) {
while ($result_usr = PMA_DBI_fetch_assoc($rs_usr)) { while ($result_usr = PMA_DBI_fetch_assoc($rs_usr)) {
if (!$is_create_priv) { if (!$is_create_db_priv) {
$is_create_priv = ($result_usr['Create_priv'] == 'Y'); $is_create_db_priv = ($result_usr['Create_priv'] == 'Y');
} }
if (!$is_reload_priv) { if (!$is_reload_priv) {
$is_reload_priv = ($result_usr['Reload_priv'] == 'Y'); $is_reload_priv = ($result_usr['Reload_priv'] == 'Y');
@@ -87,7 +101,7 @@ if (PMA_MYSQL_INT_VERSION >= 40102) {
// If the user has Create priv on a inexistant db, show him in the dialog // If the user has Create priv on a inexistant db, show him in the dialog
// the first inexistant db name that we find, in most cases it's probably // the first inexistant db name that we find, in most cases it's probably
// the one he just dropped :) // the one he just dropped :)
if (!$is_create_priv) { if (!$is_create_db_priv) {
$local_query = 'SELECT DISTINCT Db FROM mysql.db WHERE ' . PMA_convert_using('Create_priv') . ' = ' . PMA_convert_using('Y', 'quoted') . ' AND (' . PMA_convert_using('User') . ' = ' .PMA_convert_using(PMA_sqlAddslashes($mysql_cur_user), 'quoted') . ' OR ' . PMA_convert_using('User') . ' = ' . PMA_convert_using('', 'quoted') . ');'; $local_query = 'SELECT DISTINCT Db FROM mysql.db WHERE ' . PMA_convert_using('Create_priv') . ' = ' . PMA_convert_using('Y', 'quoted') . ' AND (' . PMA_convert_using('User') . ' = ' .PMA_convert_using(PMA_sqlAddslashes($mysql_cur_user), 'quoted') . ' OR ' . PMA_convert_using('User') . ' = ' . PMA_convert_using('', 'quoted') . ');';
$rs_usr = PMA_DBI_try_query($local_query, $dbh, PMA_DBI_QUERY_STORE); $rs_usr = PMA_DBI_try_query($local_query, $dbh, PMA_DBI_QUERY_STORE);
if ($rs_usr) { if ($rs_usr) {
@@ -98,7 +112,7 @@ if (PMA_MYSQL_INT_VERSION >= 40102) {
|| (!PMA_DBI_try_query('USE ' . ereg_replace($re1 . '(%|_)', '\\1\\3', $row['Db'])) && substr(PMA_DBI_getError(), 1, 4) != 1044)) { || (!PMA_DBI_try_query('USE ' . ereg_replace($re1 . '(%|_)', '\\1\\3', $row['Db'])) && substr(PMA_DBI_getError(), 1, 4) != 1044)) {
$db_to_create = ereg_replace($re0 . '%', '\\1...', ereg_replace($re0 . '_', '\\1?', $row['Db'])); $db_to_create = ereg_replace($re0 . '%', '\\1...', ereg_replace($re0 . '_', '\\1?', $row['Db']));
$db_to_create = ereg_replace($re1 . '(%|_)', '\\1\\3', $db_to_create); $db_to_create = ereg_replace($re1 . '(%|_)', '\\1\\3', $db_to_create);
$is_create_priv = TRUE; $is_create_db_priv = TRUE;
break; break;
} // end if } // end if
} // end while } // end while
@@ -117,7 +131,7 @@ if (PMA_MYSQL_INT_VERSION >= 40102) {
} }
unset($local_query); unset($local_query);
if ($rs_usr) { if ($rs_usr) {
PMA_analyseShowGrant($rs_usr,$is_create_priv, $db_to_create, $is_reload_priv); PMA_analyseShowGrant($rs_usr,$is_create_db_priv, $db_to_create, $is_reload_priv, $dbs_where_create_table_allowed);
PMA_DBI_free_result($rs_usr); PMA_DBI_free_result($rs_usr);
unset($rs_usr); unset($rs_usr);
} // end if } // end if
@@ -131,4 +145,3 @@ if (!$cfg['SuggestDBName']) {
} }
?> ?>

View File

@@ -2,11 +2,11 @@
/* $Id$ */ /* $Id$ */
// vim: expandtab sw=4 ts=4 sts=4: // vim: expandtab sw=4 ts=4 sts=4:
// Displays form for creating database (if user has priveleges for that) // Displays form for creating database (if user has privileges for that)
require_once('./libraries/check_user_privileges.lib.php'); require_once('./libraries/check_user_privileges.lib.php');
if ($is_create_priv) { if ($is_create_db_priv) {
// The user is allowed to create a db // The user is allowed to create a db
?> ?>
<form method="post" action="db_create.php"><b> <form method="post" action="db_create.php"><b>

View File

@@ -0,0 +1,78 @@
<?php
/* $Id$ */
// vim: expandtab sw=4 ts=4 sts=4:
// Displays form for creating a table (if user has privileges for that)
require_once('./libraries/check_user_privileges.lib.php');
$is_create_table_priv = FALSE;
// TODO: escaped wildcard patterns
$mysql_wildcards = array('%','_');
$preg_patterns = array('(.*)', '.');
foreach($dbs_where_create_table_allowed as $allowed_db) {
// '*' indicates a global CREATE priv
if ($allowed_db == '*' || preg_match('@' .str_replace($mysql_wildcards, $preg_patterns, $allowed_db) . '@i', $db)) {
$is_create_table_priv = TRUE;
break;
}
}
if ($is_create_table_priv) {
?>
<!-- Create a new table -->
<form method="post" action="tbl_create.php" onsubmit="return (emptyFormElements(this, 'table') && checkFormElementInRange(this, 'num_fields', '<?php echo str_replace('\'', '\\\'', $GLOBALS['strInvalidFieldCount']); ?>', 1))">
<table border="0" cellpadding="2" cellspacing="0">
<tr>
<td class="tblHeaders" colspan="3" nowrap="nowrap"><?php
echo PMA_generate_common_hidden_inputs($db);
if($cfg['PropertiesIconic']){ echo '<img src="' . $pmaThemeImage . 'b_newtbl.png" border="0" width="16" height="16" hspace="2" align="middle" />'; }
// if you want navigation:
$strDBLink = '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url() . '&amp;db=' . urlencode($GLOBALS['db']) . '">'
. htmlspecialchars($GLOBALS['db']) . '</a>';
// else use
// $strDBLink = htmlspecialchars($db);
echo ' ' . sprintf($strCreateNewTable, $strDBLink) . ':&nbsp;' . "\n";
echo ' </td></tr>';
echo ' <tr bgcolor="'.$cfg['BgcolorOne'].'"><td nowrap="nowrap">';
echo ' ' . $strName . ':&nbsp;' . "\n";
echo ' </td>';
echo ' <td nowrap="nowrap">';
echo ' ' . '<input type="text" name="table" maxlength="64" size="30" class="textfield" />';
echo ' </td><td>&nbsp;</td></tr>';
echo ' <tr bgcolor="'.$cfg['BgcolorOne'].'"><td nowrap="nowrap">';
if (!isset($strNumberOfFields)) {
$strNumberOfFields = $strFields;
}
echo ' ' . $strNumberOfFields . ':&nbsp;' . "\n";
echo ' </td>';
echo ' <td nowrap="nowrap">';
echo ' ' . '<input type="text" name="num_fields" size="2" class="textfield" />' . "\n";
echo ' </td>';
echo ' <td align="right">';
echo ' ' . '&nbsp;<input type="submit" value="' . $strGo . '" />' . "\n";
echo ' </td> </tr>';
echo ' </table>';
echo '</form>' . "\n";
} else {
?>
<table border="0" cellpadding="2" cellspacing="0">
<tr>
<td class="tblHeaders" colspan="3" nowrap="nowrap"><?php
if($cfg['PropertiesIconic']) {
echo '<img src="' . $pmaThemeImage . 'b_newtbl.png" border="0" width="16" height="16" hspace="2" align="middle" />' . "\n";
}
$strDBLink = htmlspecialchars($db);
echo ' ' . sprintf($strCreateNewTable, $strDBLink) . ':&nbsp;' . "\n";
echo ' </td></tr>' . "\n";
echo ' <tr>' . "\n";
echo ' <td>' . "\n";
echo '<span class="noPrivileges">'
. ($cfg['ErrorIconic'] ? '<img src="' . $pmaThemeImage . 's_error2.png" width="11" height="11" hspace="2" border="0" align="middle" />' : '')
. '' . $strNoPrivileges .'</span>' . "\n";
echo ' </td>' . "\n";
echo ' </tr>' . "\n";
echo ' </table>' . "\n";
} // end if
?>

View File

@@ -175,7 +175,7 @@ if ($server > 0) {
// loic1: Displays the MySQL column only if at least one feature has to be // loic1: Displays the MySQL column only if at least one feature has to be
// displayed // displayed
if ($is_superuser || $is_create_priv || $is_process_priv || $is_reload_priv if ($is_superuser || $is_create_db_priv || $is_process_priv || $is_reload_priv
|| $cfg['ShowMysqlInfo'] || $cfg['ShowMysqlVars'] || $cfg['ShowChgPassword'] || $cfg['ShowMysqlInfo'] || $cfg['ShowMysqlVars'] || $cfg['ShowChgPassword']
|| $cfg['Server']['auth_type'] != 'config') { || $cfg['Server']['auth_type'] != 'config') {
?> ?>