Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
a51ea111
Commit
a51ea111
authored
Jun 23, 2003
by
monty@narttu.mysql.fi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
SHOW GRANTS hided real grants when grants on both column and table (Bug 654)
parent
3bd661a6
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
279 additions
and
167 deletions
+279
-167
mysql-test/r/grant.result
mysql-test/r/grant.result
+42
-5
mysql-test/t/grant.test
mysql-test/t/grant.test
+32
-2
sql/sql_acl.cc
sql/sql_acl.cc
+203
-158
sql/sql_acl.h
sql/sql_acl.h
+2
-2
No files found.
mysql-test/r/grant.result
View file @
a51ea111
drop table if exists t1;
delete from mysql.user where user='mysqltest_1';
delete from mysql.db where user='mysqltest_1';
flush privileges;
...
...
@@ -64,8 +65,44 @@ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TE
revoke all privileges on mysqltest.* from mysqltest_1@localhost;
delete from mysql.user where user='mysqltest_1';
flush privileges;
grant usage on test.* to user@localhost with grant option;
show grants for user@localhost;
Grants for user@localhost
GRANT USAGE ON *.* TO 'user'@'localhost'
GRANT USAGE ON `test`.* TO 'user'@'localhost' WITH GRANT OPTION
grant usage on test.* to mysqltest_1@localhost with grant option;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT USAGE ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION
GRANT USAGE ON `test`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION
delete from mysql.user where user='mysqltest_1';
delete from mysql.db where user='mysqltest_1';
delete from mysql.tables_priv where user='mysqltest_1';
delete from mysql.columns_priv where user='mysqltest_1';
flush privileges;
create table t1 (a int);
GRANT select,update,insert on t1 to mysqltest_1@localhost;
GRANT select (a), update (a),insert(a), references(a) on t1 to mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT SELECT, SELECT (a), INSERT, INSERT (a), UPDATE, UPDATE (a), REFERENCES (a) ON `test`.`t1` TO 'mysqltest_1'@'localhost'
select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1";
table_priv column_priv
Select,Insert,Update Select,Insert,Update,References
REVOKE select (a), update on t1 from mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT SELECT, INSERT, INSERT (a), REFERENCES (a) ON `test`.`t1` TO 'mysqltest_1'@'localhost'
REVOKE insert,insert (a) on t1 from mysqltest_1@localhost;
GRANT references on t1 to mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT SELECT, REFERENCES, REFERENCES (a) ON `test`.`t1` TO 'mysqltest_1'@'localhost'
select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1";
table_priv column_priv
Select,References References
delete from mysql.user where user='mysqltest_1';
delete from mysql.db where user='mysqltest_1';
delete from mysql.tables_priv where user='mysqltest_1';
delete from mysql.columns_priv where user='mysqltest_1';
flush privileges;
drop table t1;
mysql-test/t/grant.test
View file @
a51ea111
--
disable_warnings
drop
table
if
exists
t1
;
--
enable_warnings
#
# Test that SSL options works properly
#
...
...
@@ -39,6 +43,32 @@ show grants for mysqltest_1@localhost;
revoke
all
privileges
on
mysqltest
.*
from
mysqltest_1
@
localhost
;
delete
from
mysql
.
user
where
user
=
'mysqltest_1'
;
flush
privileges
;
grant
usage
on
test
.*
to
user
@
localhost
with
grant
option
;
show
grants
for
user
@
localhost
;
grant
usage
on
test
.*
to
mysqltest_1
@
localhost
with
grant
option
;
show
grants
for
mysqltest_1
@
localhost
;
delete
from
mysql
.
user
where
user
=
'mysqltest_1'
;
delete
from
mysql
.
db
where
user
=
'mysqltest_1'
;
delete
from
mysql
.
tables_priv
where
user
=
'mysqltest_1'
;
delete
from
mysql
.
columns_priv
where
user
=
'mysqltest_1'
;
flush
privileges
;
#
# Test what happens when you have same table and colum level grants
#
create
table
t1
(
a
int
);
GRANT
select
,
update
,
insert
on
t1
to
mysqltest_1
@
localhost
;
GRANT
select
(
a
),
update
(
a
),
insert
(
a
),
references
(
a
)
on
t1
to
mysqltest_1
@
localhost
;
show
grants
for
mysqltest_1
@
localhost
;
select
table_priv
,
column_priv
from
mysql
.
tables_priv
where
user
=
"mysqltest_1"
;
REVOKE
select
(
a
),
update
on
t1
from
mysqltest_1
@
localhost
;
show
grants
for
mysqltest_1
@
localhost
;
REVOKE
insert
,
insert
(
a
)
on
t1
from
mysqltest_1
@
localhost
;
GRANT
references
on
t1
to
mysqltest_1
@
localhost
;
show
grants
for
mysqltest_1
@
localhost
;
select
table_priv
,
column_priv
from
mysql
.
tables_priv
where
user
=
"mysqltest_1"
;
delete
from
mysql
.
user
where
user
=
'mysqltest_1'
;
delete
from
mysql
.
db
where
user
=
'mysqltest_1'
;
delete
from
mysql
.
tables_priv
where
user
=
'mysqltest_1'
;
delete
from
mysql
.
columns_priv
where
user
=
'mysqltest_1'
;
flush
privileges
;
drop
table
t1
;
sql/sql_acl.cc
View file @
a51ea111
/* Copyright (C) 2000 MySQL AB
/* Copyright (C) 2000
-2003
MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
...
...
@@ -193,7 +193,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
host
.
db
=
get_field
(
&
mem
,
table
,
1
);
host
.
access
=
get_access
(
table
,
2
);
host
.
access
=
fix_rights_for_db
(
host
.
access
);
host
.
sort
=
get_sort
(
2
,
host
.
host
.
hostname
,
host
.
db
);
host
.
sort
=
get_sort
(
2
,
host
.
host
.
hostname
,
host
.
db
);
#ifndef TO_BE_REMOVED
if
(
table
->
fields
==
8
)
{
// Without grant
...
...
@@ -213,8 +213,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
if
(
table
->
field
[
2
]
->
field_length
==
8
&&
protocol_version
==
PROTOCOL_VERSION
)
{
sql_print_error
(
"Old 'user' table. (Check README or the Reference manual). Continuing --old-protocol"
);
/* purecov: tested */
sql_print_error
(
"Old 'user' table. (Check README or the Reference manual). Continuing --old-protocol"
);
/* purecov: tested */
protocol_version
=
9
;
/* purecov: tested */
}
...
...
@@ -247,7 +246,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
user
.
sort
=
get_sort
(
2
,
user
.
host
.
hostname
,
user
.
user
);
user
.
hostname_length
=
(
user
.
host
.
hostname
?
(
uint
)
strlen
(
user
.
host
.
hostname
)
:
0
);
if
(
table
->
fields
>=
31
)
/* Starting from 4.0.2 we have more fields */
if
(
table
->
fields
>=
31
)
/* Starting from 4.0.2 we have more fields */
{
char
*
ssl_type
=
get_field
(
&
mem
,
table
,
24
);
if
(
!
ssl_type
)
...
...
@@ -259,7 +258,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
else
/* !strcmp(ssl_type, "SPECIFIED") */
user
.
ssl_type
=
SSL_TYPE_SPECIFIED
;
user
.
ssl_cipher
=
get_field
(
&
mem
,
table
,
25
);
user
.
ssl_cipher
=
get_field
(
&
mem
,
table
,
25
);
user
.
x509_issuer
=
get_field
(
&
mem
,
table
,
26
);
user
.
x509_subject
=
get_field
(
&
mem
,
table
,
27
);
...
...
@@ -368,7 +367,14 @@ void acl_free(bool end)
}
}
/* Reload acl list if possible */
/*
Forget current privileges and read new privileges from the privilege tables
SYNOPSIS
acl_reload()
thd Thread handle
*/
void
acl_reload
(
THD
*
thd
)
{
...
...
@@ -493,8 +499,8 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
ulong
acl_getroot
(
THD
*
thd
,
const
char
*
host
,
const
char
*
ip
,
const
char
*
user
,
const
char
*
password
,
const
char
*
message
,
char
**
priv_user
,
char
*
priv_host
,
bool
old_ver
,
USER_RESOURCES
*
mqh
)
char
**
priv_user
,
char
*
priv_host
,
bool
old_ver
,
USER_RESOURCES
*
mqh
)
{
ulong
user_access
=
NO_ACCESS
;
*
priv_user
=
(
char
*
)
user
;
...
...
@@ -526,15 +532,15 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
{
#ifdef HAVE_OPENSSL
Vio
*
vio
=
thd
->
net
.
vio
;
/*
/*
In this point we know that user is allowed to connect
from given host by given username/password pair. Now
we check if SSL is required, if user is using SSL and
if X509 certificate attributes are OK
*/
switch
(
acl_user
->
ssl_type
)
{
switch
(
acl_user
->
ssl_type
)
{
case
SSL_TYPE_NOT_SPECIFIED
:
// Impossible
case
SSL_TYPE_NONE
:
/* SSL is not required to connect */
case
SSL_TYPE_NONE
:
/* SSL is not required to connect */
user_access
=
acl_user
->
access
;
break
;
case
SSL_TYPE_ANY
:
/* Any kind of SSL is good enough */
...
...
@@ -544,7 +550,7 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
case
SSL_TYPE_X509
:
/* Client should have any valid certificate. */
/*
We need to check for absence of SSL because without SSL
we should reject connection.
we should reject connection.
*/
if
(
vio_type
(
vio
)
==
VIO_TYPE_SSL
&&
SSL_get_peer_certificate
(
vio
->
ssl_
))
user_access
=
acl_user
->
access
;
...
...
@@ -653,12 +659,12 @@ static byte* check_get_key(ACL_USER *buff,uint *length,
}
static
void
acl_update_user
(
const
char
*
user
,
const
char
*
host
,
const
char
*
password
,
const
char
*
password
,
enum
SSL_type
ssl_type
,
const
char
*
ssl_cipher
,
const
char
*
x509_issuer
,
const
char
*
x509_subject
,
USER_RESOURCES
*
mqh
,
USER_RESOURCES
*
mqh
,
ulong
privileges
)
{
for
(
uint
i
=
0
;
i
<
acl_users
.
elements
;
i
++
)
...
...
@@ -707,7 +713,7 @@ static void acl_update_user(const char *user, const char *host,
static
void
acl_insert_user
(
const
char
*
user
,
const
char
*
host
,
const
char
*
password
,
const
char
*
password
,
enum
SSL_type
ssl_type
,
const
char
*
ssl_cipher
,
const
char
*
x509_issuer
,
...
...
@@ -805,9 +811,10 @@ static void acl_insert_db(const char *user, const char *host, const char *db,
}
/*****************************************************************************
** Get privilege for a host, user and db combination
*****************************************************************************/
/*
Get privilege for a host, user and db combination
*/
ulong
acl_get
(
const
char
*
host
,
const
char
*
ip
,
const
char
*
bin_ip
,
const
char
*
user
,
const
char
*
db
)
...
...
@@ -929,11 +936,14 @@ int wild_case_compare(const char *str,const char *wildstr)
DBUG_RETURN
(
*
str
!=
'\0'
);
}
/*****************************************************************************
** check if there are any possible matching entries for this host
** All host names without wild cards are stored in a hash table,
** entries with wildcards are stored in a dynamic array
*****************************************************************************/
/*
Check if there are any possible matching entries for this host
NOTES
All host names without wild cards are stored in a hash table,
entries with wildcards are stored in a dynamic array
*/
static
void
init_check_host
(
void
)
{
...
...
@@ -1006,10 +1016,6 @@ bool acl_check_host(const char *host, const char *ip)
return
1
;
// Host is not allowed
}
/*****************************************************************************
Change password for the user if it's not an anonymous user
Note: This should write the error directly to the client!
*****************************************************************************/
/*
Check if the user is allowed to change password
...
...
@@ -1021,8 +1027,8 @@ bool acl_check_host(const char *host, const char *ip)
user user name
RETURN VALUE
0
OK
1
ERROR ; In this case the error is sent to the client.
0
OK
1
ERROR ; In this case the error is sent to the client.
*/
bool
check_change_password
(
THD
*
thd
,
const
char
*
host
,
const
char
*
user
)
...
...
@@ -1061,7 +1067,7 @@ bool check_change_password(THD *thd, const char *host, const char *user)
RETURN VALUES
0 ok
1 ERROR; In this case the error is sent to the client.
*/
*/
bool
change_password
(
THD
*
thd
,
const
char
*
host
,
const
char
*
user
,
char
*
new_password
)
...
...
@@ -1127,7 +1133,7 @@ find_acl_user(const char *host, const char *user)
{
ACL_USER
*
acl_user
=
dynamic_element
(
&
acl_users
,
i
,
ACL_USER
*
);
DBUG_PRINT
(
"info"
,(
"strcmp('%s','%s'), compare_hostname('%s','%s'),"
,
user
,
acl_user
->
user
,(
host
),(
acl_user
->
host
)));
user
,
acl_user
->
user
,(
host
),(
acl_user
->
host
)));
if
(
!
acl_user
->
user
&&
!
user
[
0
]
||
acl_user
->
user
&&
!
strcmp
(
user
,
acl_user
->
user
))
{
...
...
@@ -1140,15 +1146,18 @@ find_acl_user(const char *host, const char *user)
DBUG_RETURN
(
0
);
}
/*****************************************************************************
Handle comparing of hostname
A hostname may be of type:
hostname (May include wildcards); monty.pp.sci.fi
ip (May include wildcards); 192.168.0.0
ip/netmask 192.168.0.0/255.255.255.0
A net mask of 0.0.0.0 is not allowed.
*****************************************************************************/
/*
Comparing of hostnames
NOTES
A hostname may be of type:
hostname (May include wildcards); monty.pp.sci.fi
ip (May include wildcards); 192.168.0.0
ip/netmask 192.168.0.0/255.255.255.0
A net mask of 0.0.0.0 is not allowed.
*/
static
const
char
*
calc_ip
(
const
char
*
ip
,
long
*
val
,
char
end
)
{
...
...
@@ -1195,9 +1204,9 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
}
/*
***************************************************************************
Code to u
pdate grants in the user and database privilege tables
*
***************************************************************************
/
/*
U
pdate grants in the user and database privilege tables
*/
static
bool
update_user_table
(
THD
*
thd
,
const
char
*
host
,
const
char
*
user
,
const
char
*
new_password
)
...
...
@@ -1263,7 +1272,7 @@ static bool test_if_create_new_users(THD *thd)
/****************************************************************************
**
Handle GRANT commands
Handle GRANT commands
****************************************************************************/
static
int
replace_user_table
(
THD
*
thd
,
TABLE
*
table
,
const
LEX_USER
&
combo
,
...
...
@@ -1285,8 +1294,8 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
if
(
combo
.
password
.
length
!=
HASH_PASSWORD_LENGTH
)
{
my_printf_error
(
ER_PASSWORD_NO_MATCH
,
"Password hash should be a %d-digit hexadecimal number"
,
MYF
(
0
),
HASH_PASSWORD_LENGTH
);
"Password hash should be a %d-digit hexadecimal number"
,
MYF
(
0
),
HASH_PASSWORD_LENGTH
);
DBUG_RETURN
(
-
1
);
}
password
=
combo
.
password
.
str
;
...
...
@@ -1459,7 +1468,7 @@ static int replace_db_table(TABLE *table, const char *db,
char
what
=
(
revoke_grant
)
?
'N'
:
'Y'
;
DBUG_ENTER
(
"replace_db_table"
);
/
/ is there such a user in user table in memory ????
/
* Check if there is such a user in user table in memory? */
if
(
!
initialized
||
!
find_acl_user
(
combo
.
host
.
str
,
combo
.
user
.
str
))
{
my_error
(
ER_PASSWORD_NO_MATCH
,
MYF
(
0
));
...
...
@@ -1471,7 +1480,7 @@ static int replace_db_table(TABLE *table, const char *db,
table
->
field
[
2
]
->
store
(
combo
.
user
.
str
,
combo
.
user
.
length
);
table
->
file
->
index_init
(
0
);
if
(
table
->
file
->
index_read
(
table
->
record
[
0
],(
byte
*
)
table
->
field
[
0
]
->
ptr
,
0
,
HA_READ_KEY_EXACT
))
HA_READ_KEY_EXACT
))
{
if
(
what
==
'N'
)
{
// no row, no revoke
...
...
@@ -1502,7 +1511,7 @@ static int replace_db_table(TABLE *table, const char *db,
if
(
old_row_exists
)
{
/
/ update old existing row
/
* update old existing row */
if
(
rights
)
{
if
((
error
=
table
->
file
->
update_row
(
table
->
record
[
1
],
table
->
record
[
0
])))
...
...
@@ -1529,11 +1538,11 @@ static int replace_db_table(TABLE *table, const char *db,
DBUG_RETURN
(
0
);
/* This could only happen if the grant tables got corrupted */
table_error:
table_error:
table
->
file
->
print_error
(
error
,
MYF
(
0
));
/* purecov: deadcode */
table
->
file
->
index_end
();
abort:
abort:
DBUG_RETURN
(
-
1
);
}
...
...
@@ -1649,7 +1658,7 @@ public:
if
(
!
(
mem_check
=
new
GRANT_COLUMN
(
*
res
,
fix_rights_for_column
(
priv
))))
{
/
/ Don't use this entry
/
* Don't use this entry */
privs
=
cols
=
0
;
/* purecov: deadcode */
return
;
/* purecov: deadcode */
}
...
...
@@ -1827,7 +1836,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
key_length
,
HA_READ_KEY_EXACT
))
goto
end
;
/
/ Scan trough all rows with the same host,db,user and table
/
* Scan through all rows with the same host,db,user and table */
do
{
ulong
privileges
=
(
ulong
)
table
->
field
[
6
]
->
val_int
();
...
...
@@ -1877,7 +1886,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
!
key_cmp
(
table
,
key
,
0
,
key_length
));
}
end:
end:
table
->
file
->
index_end
();
DBUG_RETURN
(
result
);
}
...
...
@@ -1947,7 +1956,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
if
(
revoke_grant
)
{
/
/ column rights are already fixed in mysql_table_grant !
/
* column rights are already fixed in mysql_table_grant */
store_table_rights
=
j
&
~
store_table_rights
;
}
else
...
...
@@ -1983,7 +1992,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
if
(
rights
|
col_rights
)
{
grant_table
->
privs
=
rights
;
grant_table
->
cols
=
col_rights
;
grant_table
->
cols
=
col_rights
;
}
else
{
...
...
@@ -1991,19 +2000,36 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
}
DBUG_RETURN
(
0
);
/* This should never happen */
table_error:
/* This should never happen */
table_error:
table
->
file
->
print_error
(
error
,
MYF
(
0
));
/* purecov: deadcode */
DBUG_RETURN
(
-
1
);
/* purecov: deadcode */
}
/*
Store table level and column level grants in the privilege tables
SYNOPSIS
mysql_table_grant()
thd Thread handle
table_list List of tables to give grant
user_list List of users to give grant
columns List of columns to give grant
rights Table level grant
revoke_grant Set to 1 if this is a REVOKE command
RETURN
0 ok
1 error
*/
int
mysql_table_grant
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
LEX_USER
>
&
user_list
,
List
<
LEX_COLUMN
>
&
columns
,
ulong
rights
,
bool
revoke_grant
)
{
ulong
column_priv
=
0
;
ulong
column_priv
=
0
;
List_iterator
<
LEX_USER
>
str_list
(
user_list
);
LEX_USER
*
Str
;
TABLE_LIST
tables
[
3
];
...
...
@@ -2024,21 +2050,21 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
if
(
columns
.
elements
&&
!
revoke_grant
)
{
TABLE
*
table
;
class
LEX_COLUMN
*
c
heck
;
List_iterator
<
LEX_COLUMN
>
iter
(
columns
);
class
LEX_COLUMN
*
c
olumn
;
List_iterator
<
LEX_COLUMN
>
column_
iter
(
columns
);
if
(
!
(
table
=
open_ltable
(
thd
,
table_list
,
TL_READ
)))
DBUG_RETURN
(
-
1
);
while
((
c
heck
=
iter
++
))
while
((
c
olumn
=
column_
iter
++
))
{
if
(
!
find_field_in_table
(
thd
,
table
,
c
heck
->
column
.
ptr
(),
c
heck
->
column
.
length
(),
0
,
0
))
if
(
!
find_field_in_table
(
thd
,
table
,
c
olumn
->
column
.
ptr
(),
c
olumn
->
column
.
length
(),
0
,
0
))
{
my_printf_error
(
ER_BAD_FIELD_ERROR
,
ER
(
ER_BAD_FIELD_ERROR
),
MYF
(
0
),
c
heck
->
column
.
c_ptr
(),
table_list
->
alias
);
c
olumn
->
column
.
c_ptr
(),
table_list
->
alias
);
DBUG_RETURN
(
-
1
);
}
column_priv
|=
check
->
rights
|
(
rights
&
COL_ACLS
)
;
column_priv
|=
column
->
rights
;
}
close_thread_tables
(
thd
);
}
...
...
@@ -2148,21 +2174,21 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
/* If revoke_grant, calculate the new column privilege for tables_priv */
if
(
revoke_grant
)
{
class
LEX_COLUMN
*
c
heck
;
List_iterator
<
LEX_COLUMN
>
iter
(
columns
);
class
LEX_COLUMN
*
c
olumn
;
List_iterator
<
LEX_COLUMN
>
column_
iter
(
columns
);
GRANT_COLUMN
*
grant_column
;
/* Fix old grants */
while
((
c
heck
=
iter
++
))
while
((
c
olumn
=
column_
iter
++
))
{
grant_column
=
column_hash_search
(
grant_table
,
c
heck
->
column
.
ptr
(),
c
heck
->
column
.
length
());
c
olumn
->
column
.
ptr
(),
c
olumn
->
column
.
length
());
if
(
grant_column
)
grant_column
->
rights
&=
~
(
c
heck
->
rights
|
rights
);
grant_column
->
rights
&=
~
(
c
olumn
->
rights
|
rights
);
}
/* scan trough all columns to get new column grant */
column_priv
=
0
;
column_priv
=
0
;
for
(
uint
idx
=
0
;
idx
<
grant_table
->
hash_columns
.
records
;
idx
++
)
{
grant_column
=
(
GRANT_COLUMN
*
)
hash_element
(
&
grant_table
->
hash_columns
,
...
...
@@ -2259,7 +2285,7 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list,
if
(
!
revoke_grant
)
create_new_users
=
test_if_create_new_users
(
thd
);
/
/ go through users in user_list
/
* go through users in user_list */
pthread_mutex_lock
(
&
LOCK_grant
);
VOID
(
pthread_mutex_lock
(
&
acl_cache
->
lock
));
grant_version
++
;
...
...
@@ -2280,7 +2306,7 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list,
continue
;
}
if
((
replace_user_table
(
thd
,
tables
[
0
].
table
,
tables
[
0
].
table
,
*
Str
,
(
!
db
?
rights
:
0
),
revoke_grant
,
create_new_users
)))
...
...
@@ -2401,7 +2427,16 @@ end:
}
/* Reload grant array if possible */
/*
Reload grant array if possible
SYNOPSIS
grant_reload()
thd Thread handler
NOTES
Locked tables are checked by acl_init and doesn't have to be checked here
*/
void
grant_reload
(
THD
*
thd
)
{
...
...
@@ -2410,8 +2445,6 @@ void grant_reload(THD *thd)
MEM_ROOT
old_mem
;
DBUG_ENTER
(
"grant_reload"
);
// Locked tables are checked by acl_init and doesn't have to be checked here
pthread_mutex_lock
(
&
LOCK_grant
);
grant_version
++
;
old_hash_tables
=
hash_tables
;
...
...
@@ -2487,13 +2520,13 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
pthread_mutex_unlock
(
&
LOCK_grant
);
return
0
;
err:
err:
pthread_mutex_unlock
(
&
LOCK_grant
);
if
(
!
no_errors
)
// Not a silent skip of table
{
const
char
*
command
=
""
;
if
(
want_access
&
SELECT_ACL
)
command
=
"select"
;
command
=
"select"
;
else
if
(
want_access
&
INSERT_ACL
)
command
=
"insert"
;
else
if
(
want_access
&
UPDATE_ACL
)
...
...
@@ -2534,7 +2567,7 @@ bool check_grant_column(THD *thd,TABLE *table, const char *name,
pthread_mutex_lock
(
&
LOCK_grant
);
/
/ reload table if someone has modified any grants
/
* reload table if someone has modified any grants */
if
(
table
->
grant
.
version
!=
grant_version
)
{
...
...
@@ -2594,7 +2627,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
pthread_mutex_lock
(
&
LOCK_grant
);
/
/ reload table if someone has modified any grants
/
* reload table if someone has modified any grants */
if
(
table
->
grant
.
version
!=
grant_version
)
{
...
...
@@ -2604,7 +2637,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
table
->
real_name
,
0
);
/* purecov: inspected */
table
->
grant
.
version
=
grant_version
;
/* purecov: inspected */
}
/
/ The following should always be true
/
* The following should always be true */
if
(
!
(
grant_table
=
table
->
grant
.
grant_table
))
goto
err
;
/* purecov: inspected */
...
...
@@ -2619,7 +2652,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
return
0
;
/* We must use my_printf_error() here! */
err:
err:
pthread_mutex_unlock
(
&
LOCK_grant
);
const
char
*
command
=
""
;
...
...
@@ -2639,11 +2672,11 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
}
/*
***************************************************************************
/*
Check if a user has the right to access a database
Access is accepted if he has a grant for any table in the database
Return 1 if access is denied
*
***************************************************************************
/
*/
bool
check_grant_db
(
THD
*
thd
,
const
char
*
db
)
{
...
...
@@ -2683,7 +2716,7 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table)
pthread_mutex_lock
(
&
LOCK_grant
);
grant_table
=
table_hash_search
(
thd
->
host
,
thd
->
ip
,
db
,
user
,
table
->
real_name
,
0
);
table
->
real_name
,
0
);
table
->
grant
.
grant_table
=
grant_table
;
// Remember for column test
table
->
grant
.
version
=
grant_version
;
if
(
grant_table
)
...
...
@@ -2701,7 +2734,7 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field)
ulong
priv
;
pthread_mutex_lock
(
&
LOCK_grant
);
/
/ reload table if someone has modified any grants
/
* reload table if someone has modified any grants */
if
(
table
->
grant
.
version
!=
grant_version
)
{
table
->
grant
.
grant_table
=
...
...
@@ -2726,11 +2759,20 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field)
return
priv
;
}
/* Help function for mysql_show_grants */
/*****************************************************************************
SHOW GRANTS : send to client grant-like strings depicting user@host
privileges
*****************************************************************************/
static
void
add_user_option
(
String
*
grant
,
ulong
value
,
const
char
*
name
)
{
if
(
value
)
{
char
buff
[
22
],
*
p
;
// just as in int2str
grant
->
append
(
' '
);
grant
->
append
(
name
,
strlen
(
name
));
grant
->
append
(
' '
);
p
=
int10_to_str
(
value
,
buff
,
10
);
grant
->
append
(
buff
,
p
-
buff
);
}
}
static
const
char
*
command_array
[]
=
{
...
...
@@ -2739,13 +2781,21 @@ static const char *command_array[]=
"SUPER"
,
"CREATE TEMPORARY TABLES"
,
"LOCK TABLES"
,
"EXECUTE"
,
"REPLICATION SLAVE"
,
"REPLICATION CLIENT"
,
};
static
uint
command_lengths
[]
=
{
6
,
6
,
6
,
6
,
6
,
4
,
6
,
8
,
7
,
4
,
5
,
10
,
5
,
5
,
14
,
5
,
23
,
11
,
7
,
17
,
18
};
int
mysql_show_grants
(
THD
*
thd
,
LEX_USER
*
lex_user
)
/*
SHOW GRANTS; Send grants for a user to the client
IMPLEMENTATION
Send to client grant-like strings depicting user@host privileges
*/
int
mysql_show_grants
(
THD
*
thd
,
LEX_USER
*
lex_user
)
{
ulong
want_access
;
uint
counter
,
index
;
...
...
@@ -2784,7 +2834,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
!
my_strcasecmp
(
lex_user
->
host
.
str
,
host
))
break
;
}
if
(
counter
==
acl_users
.
elements
)
if
(
counter
==
acl_users
.
elements
)
{
my_printf_error
(
ER_NONEXISTING_GRANT
,
ER
(
ER_NONEXISTING_GRANT
),
MYF
(
0
),
lex_user
->
user
.
str
,
lex_user
->
host
.
str
);
...
...
@@ -2815,13 +2865,13 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global
.
append
(
"ALL PRIVILEGES"
,
14
);
else
if
(
!
(
want_access
&
~
GRANT_ACL
))
global
.
append
(
"USAGE"
,
5
);
else
else
{
bool
found
=
0
;
ulong
j
,
test_access
=
want_access
&
~
GRANT_ACL
;
for
(
counter
=
0
,
j
=
SELECT_ACL
;
j
<=
GLOBAL_ACLS
;
counter
++
,
j
<<=
1
)
{
if
(
test_access
&
j
)
if
(
test_access
&
j
)
{
if
(
found
)
global
.
append
(
", "
,
2
);
...
...
@@ -2831,7 +2881,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
}
}
global
.
append
(
" ON *.* TO '"
,
12
);
global
.
append
(
lex_user
->
user
.
str
,
lex_user
->
user
.
length
);
global
.
append
(
lex_user
->
user
.
str
,
lex_user
->
user
.
length
);
global
.
append
(
"'@'"
,
3
);
global
.
append
(
lex_user
->
host
.
str
,
lex_user
->
host
.
length
);
global
.
append
(
'\''
);
...
...
@@ -2854,25 +2904,25 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global
.
append
(
" REQUIRE "
,
9
);
if
(
acl_user
->
x509_issuer
)
{
ssl_options
++
;
global
.
append
(
"ISSUER
\'
"
,
8
);
global
.
append
(
acl_user
->
x509_issuer
,
strlen
(
acl_user
->
x509_issuer
));
ssl_options
++
;
global
.
append
(
"ISSUER
\'
"
,
8
);
global
.
append
(
acl_user
->
x509_issuer
,
strlen
(
acl_user
->
x509_issuer
));
global
.
append
(
'\''
);
}
if
(
acl_user
->
x509_subject
)
{
if
(
ssl_options
++
)
global
.
append
(
' '
);
global
.
append
(
"SUBJECT
\'
"
,
9
);
global
.
append
(
acl_user
->
x509_subject
,
strlen
(
acl_user
->
x509_subject
));
if
(
ssl_options
++
)
global
.
append
(
' '
);
global
.
append
(
"SUBJECT
\'
"
,
9
);
global
.
append
(
acl_user
->
x509_subject
,
strlen
(
acl_user
->
x509_subject
));
global
.
append
(
'\''
);
}
if
(
acl_user
->
ssl_cipher
)
{
if
(
ssl_options
++
)
global
.
append
(
' '
);
global
.
append
(
"CIPHER '"
,
8
);
global
.
append
(
acl_user
->
ssl_cipher
,
strlen
(
acl_user
->
ssl_cipher
));
if
(
ssl_options
++
)
global
.
append
(
' '
);
global
.
append
(
"CIPHER '"
,
8
);
global
.
append
(
acl_user
->
ssl_cipher
,
strlen
(
acl_user
->
ssl_cipher
));
global
.
append
(
'\''
);
}
}
...
...
@@ -2880,30 +2930,15 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
(
acl_user
->
user_resource
.
questions
|
acl_user
->
user_resource
.
updates
|
acl_user
->
user_resource
.
connections
))
{
global
.
append
(
" WITH"
,
5
);
global
.
append
(
" WITH"
,
5
);
if
(
want_access
&
GRANT_ACL
)
global
.
append
(
" GRANT OPTION"
,
13
);
if
(
acl_user
->
user_resource
.
questions
)
{
char
buff
[
22
],
*
p
;
// just as in int2str
global
.
append
(
" MAX_QUERIES_PER_HOUR "
,
22
);
p
=
int10_to_str
(
acl_user
->
user_resource
.
questions
,
buff
,
10
);
global
.
append
(
buff
,
p
-
buff
);
}
if
(
acl_user
->
user_resource
.
updates
)
{
char
buff
[
22
],
*
p
;
// just as in int2str
global
.
append
(
" MAX_UPDATES_PER_HOUR "
,
22
);
p
=
int10_to_str
(
acl_user
->
user_resource
.
updates
,
buff
,
10
);
global
.
append
(
buff
,
p
-
buff
);
}
if
(
acl_user
->
user_resource
.
connections
)
{
char
buff
[
22
],
*
p
;
// just as in int2str
global
.
append
(
" MAX_CONNECTIONS_PER_HOUR "
,
26
);
p
=
int10_to_str
(
acl_user
->
user_resource
.
connections
,
buff
,
10
);
global
.
append
(
buff
,
p
-
buff
);
}
global
.
append
(
" GRANT OPTION"
,
13
);
add_user_option
(
&
global
,
acl_user
->
user_resource
.
questions
,
"MAX_QUERIES_PER_HOUR"
);
add_user_option
(
&
global
,
acl_user
->
user_resource
.
updates
,
"MAX_UPDATES_PER_HOUR"
);
add_user_option
(
&
global
,
acl_user
->
user_resource
.
connections
,
"MAX_CONNECTIONS_PER_HOUR"
);
}
thd
->
packet
.
length
(
0
);
net_store_data
(
&
thd
->
packet
,
global
.
ptr
(),
global
.
length
());
...
...
@@ -2929,7 +2964,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
!
my_strcasecmp
(
lex_user
->
host
.
str
,
host
))
{
want_access
=
acl_db
->
access
;
if
(
want_access
)
if
(
want_access
)
{
String
db
(
buff
,
sizeof
(
buff
));
db
.
length
(
0
);
...
...
@@ -2938,7 +2973,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if
(
test_all_bits
(
want_access
,(
DB_ACLS
&
~
GRANT_ACL
)))
db
.
append
(
"ALL PRIVILEGES"
,
14
);
else
if
(
!
(
want_access
&
~
GRANT_ACL
))
db
.
append
(
"USAGE"
,
5
);
db
.
append
(
"USAGE"
,
5
);
else
{
int
found
=
0
,
cnt
;
...
...
@@ -2954,13 +2989,13 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
}
}
}
db
.
append
(
" ON `"
,
5
);
db
.
append
(
" ON `"
,
5
);
db
.
append
(
acl_db
->
db
);
db
.
append
(
"`.* TO '"
,
8
);
db
.
append
(
lex_user
->
user
.
str
,
lex_user
->
user
.
length
);
db
.
append
(
"'@'"
,
3
);
db
.
append
(
"`.* TO '"
,
8
);
db
.
append
(
lex_user
->
user
.
str
,
lex_user
->
user
.
length
);
db
.
append
(
"'@'"
,
3
);
db
.
append
(
lex_user
->
host
.
str
,
lex_user
->
host
.
length
);
db
.
append
(
'\''
);
db
.
append
(
'\''
);
if
(
want_access
&
GRANT_ACL
)
db
.
append
(
" WITH GRANT OPTION"
,
18
);
thd
->
packet
.
length
(
0
);
...
...
@@ -2979,7 +3014,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
for
(
index
=
0
;
index
<
hash_tables
.
records
;
index
++
)
{
const
char
*
user
,
*
host
;
GRANT_TABLE
*
grant_table
=
(
GRANT_TABLE
*
)
hash_element
(
&
hash_tables
,
index
);
GRANT_TABLE
*
grant_table
=
(
GRANT_TABLE
*
)
hash_element
(
&
hash_tables
,
index
);
if
(
!
(
user
=
grant_table
->
user
))
user
=
""
;
...
...
@@ -2989,44 +3024,54 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if
(
!
strcmp
(
lex_user
->
user
.
str
,
user
)
&&
!
my_strcasecmp
(
lex_user
->
host
.
str
,
host
))
{
want_access
=
grant_table
->
privs
;
if
((
want
_access
|
grant_table
->
cols
)
!=
0
)
ulong
table_access
=
grant_table
->
privs
;
if
((
table
_access
|
grant_table
->
cols
)
!=
0
)
{
String
global
(
buff
,
sizeof
(
buff
));
global
.
length
(
0
);
global
.
append
(
"GRANT "
,
6
);
if
(
test_all_bits
(
grant_table
->
privs
,
(
TABLE_ACLS
&
~
GRANT_ACL
)))
if
(
test_all_bits
(
table_access
,
(
TABLE_ACLS
&
~
GRANT_ACL
)))
global
.
append
(
"ALL PRIVILEGES"
,
14
);
else
else
{
int
found
=
0
;
ulong
j
,
test_access
=
(
want
_access
|
grant_table
->
cols
)
&
~
GRANT_ACL
;
int
found
=
0
;
ulong
j
,
test_access
=
(
table
_access
|
grant_table
->
cols
)
&
~
GRANT_ACL
;
for
(
counter
=
0
,
j
=
SELECT_ACL
;
j
<=
TABLE_ACLS
;
counter
++
,
j
<<=
1
)
for
(
counter
=
0
,
j
=
SELECT_ACL
;
j
<=
TABLE_ACLS
;
counter
++
,
j
<<=
1
)
{
if
(
test_access
&
j
)
if
(
test_access
&
j
)
{
if
(
found
)
global
.
append
(
", "
,
2
);
found
=
1
;
found
=
1
;
global
.
append
(
command_array
[
counter
],
command_lengths
[
counter
]);
if
(
grant_table
->
cols
)
if
(
grant_table
->
cols
)
{
uint
found_col
=
0
;
uint
found_col
=
0
;
for
(
uint
col_index
=
0
;
col_index
<
grant_table
->
hash_columns
.
records
;
col_index
++
)
{
GRANT_COLUMN
*
grant_column
=
(
GRANT_COLUMN
*
)
hash_element
(
&
grant_table
->
hash_columns
,
col_index
);
if
(
grant_column
->
rights
&
j
)
if
(
grant_column
->
rights
&
j
)
{
if
(
!
found_col
)
if
(
!
found_col
)
{
found_col
=
1
;
/*
If we have a duplicated table level privilege, we
must write the access privilege name again.
*/
if
(
table_access
&
j
)
{
global
.
append
(
", "
,
2
);
global
.
append
(
command_array
[
counter
],
command_lengths
[
counter
]);
}
global
.
append
(
" ("
,
2
);
found_col
=
1
;
}
else
global
.
append
(
", "
,
2
);
...
...
@@ -3045,12 +3090,12 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global
.
append
(
"`.`"
,
3
);
global
.
append
(
grant_table
->
tname
);
global
.
append
(
"` TO '"
,
6
);
global
.
append
(
lex_user
->
user
.
str
,
lex_user
->
user
.
length
);
global
.
append
(
lex_user
->
user
.
str
,
lex_user
->
user
.
length
);
global
.
append
(
"'@'"
,
3
);
global
.
append
(
lex_user
->
host
.
str
,
lex_user
->
host
.
length
);
global
.
append
(
lex_user
->
host
.
str
,
lex_user
->
host
.
length
);
global
.
append
(
'\''
);
if
(
want
_access
&
GRANT_ACL
)
global
.
append
(
" WITH GRANT OPTION"
,
18
);
if
(
table
_access
&
GRANT_ACL
)
global
.
append
(
" WITH GRANT OPTION"
,
18
);
thd
->
packet
.
length
(
0
);
net_store_data
(
&
thd
->
packet
,
global
.
ptr
(),
global
.
length
());
if
(
my_net_write
(
&
thd
->
net
,(
char
*
)
thd
->
packet
.
ptr
(),
...
...
@@ -3063,7 +3108,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
}
}
end:
end:
VOID
(
pthread_mutex_unlock
(
&
acl_cache
->
lock
));
pthread_mutex_unlock
(
&
LOCK_grant
);
...
...
sql/sql_acl.h
View file @
a51ea111
...
...
@@ -76,8 +76,8 @@
#define get_rights_for_db(A) (((A) & 63) | (((A) & DB_CHUNK1) >> 4) | (((A) & DB_CHUNK2) >> 6))
#define fix_rights_for_table(A) (((A) & 63) | (((A) & ~63) << 4))
#define get_rights_for_table(A) (((A) & 63) | (((A) & ~63) >> 4))
#define fix_rights_for_column(A) (((A) & 7) | (((A) & ~7) <<
7
))
#define get_rights_for_column(A) (((A) & 7) | ((
(A) & ~7) >> 7
))
#define fix_rights_for_column(A) (((A) & 7) | (((A) & ~7) <<
8
))
#define get_rights_for_column(A) (((A) & 7) | ((
A) >> 8
))
/* prototypes */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment