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
daf0345a
Commit
daf0345a
authored
Oct 18, 2013
by
Vicențiu Ciorbaru
Committed by
Sergei Golubchik
Oct 18, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added recursive database roles privilege propagation.
The privileges are not correctly updated via grant commands yet.
parent
766ae81a
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
201 additions
and
7 deletions
+201
-7
mysql-test/r/acl_roles_set_role-database-recursive.result
mysql-test/r/acl_roles_set_role-database-recursive.result
+55
-0
mysql-test/t/acl_roles_set_role-database-recursive.test
mysql-test/t/acl_roles_set_role-database-recursive.test
+51
-0
sql/sql_acl.cc
sql/sql_acl.cc
+95
-7
No files found.
mysql-test/r/acl_roles_set_role-database-recursive.result
0 → 100644
View file @
daf0345a
create user 'test_user'@'localhost';
create user 'test_role1'@'';
create user 'test_role2'@'';
update mysql.user set is_role='Y' where user='test_role1';
update mysql.user set is_role='Y' where user='test_role2';
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
'test_user',
'test_role1');
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('localhost',
'test_user',
'test_role2');
insert into mysql.roles_mapping (HostFk, UserFk, RoleFk) values ('',
'test_role1',
'test_role2');
select user, host from mysql.user where user not like 'root';
user host
test_role1
test_role2
test_user localhost
select * from mysql.roles_mapping;
HostFk UserFk RoleFk
test_role1 test_role2
localhost test_user test_role1
localhost test_user test_role2
flush privileges;
select user, host from mysql.db;
user host
%
%
grant select on mysql.* to test_role2@'';
flush privileges;
select * from mysql.roles_mapping;
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping'
set role test_role1;
select * from mysql.roles_mapping;
HostFk UserFk RoleFk
test_role1 test_role2
localhost test_user test_role1
localhost test_user test_role2
set role none;
select * from mysql.roles_mapping;
ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping'
set role test_role2;
select * from mysql.roles_mapping;
HostFk UserFk RoleFk
test_role1 test_role2
localhost test_user test_role1
localhost test_user test_role2
drop user 'test_user'@'localhost';
revoke select on mysql.* from test_role2@'';
delete from mysql.user where user='test_role1';
delete from mysql.user where user='test_role2';
delete from mysql.roles_mapping where RoleFk='test_role1';
delete from mysql.roles_mapping where RoleFk='test_role2';
flush privileges;
mysql-test/t/acl_roles_set_role-database-recursive.test
0 → 100644
View file @
daf0345a
#create a user with no privileges
create
user
'test_user'
@
'localhost'
;
create
user
'test_role1'
@
''
;
create
user
'test_role2'
@
''
;
update
mysql
.
user
set
is_role
=
'Y'
where
user
=
'test_role1'
;
update
mysql
.
user
set
is_role
=
'Y'
where
user
=
'test_role2'
;
insert
into
mysql
.
roles_mapping
(
HostFk
,
UserFk
,
RoleFk
)
values
(
'localhost'
,
'test_user'
,
'test_role1'
);
insert
into
mysql
.
roles_mapping
(
HostFk
,
UserFk
,
RoleFk
)
values
(
'localhost'
,
'test_user'
,
'test_role2'
);
insert
into
mysql
.
roles_mapping
(
HostFk
,
UserFk
,
RoleFk
)
values
(
''
,
'test_role1'
,
'test_role2'
);
--
sorted_result
select
user
,
host
from
mysql
.
user
where
user
not
like
'root'
;
--
sorted_result
select
*
from
mysql
.
roles_mapping
;
flush
privileges
;
--
sorted_result
select
user
,
host
from
mysql
.
db
;
grant
select
on
mysql
.*
to
test_role2
@
''
;
flush
privileges
;
change_user
'test_user'
;
--
error
ER_TABLEACCESS_DENIED_ERROR
select
*
from
mysql
.
roles_mapping
;
set
role
test_role1
;
--
sorted_result
select
*
from
mysql
.
roles_mapping
;
set
role
none
;
--
error
ER_TABLEACCESS_DENIED_ERROR
select
*
from
mysql
.
roles_mapping
;
set
role
test_role2
;
--
sorted_result
select
*
from
mysql
.
roles_mapping
;
change_user
'root'
;
drop
user
'test_user'
@
'localhost'
;
revoke
select
on
mysql
.*
from
test_role2
@
''
;
delete
from
mysql
.
user
where
user
=
'test_role1'
;
delete
from
mysql
.
user
where
user
=
'test_role2'
;
delete
from
mysql
.
roles_mapping
where
RoleFk
=
'test_role1'
;
delete
from
mysql
.
roles_mapping
where
RoleFk
=
'test_role2'
;
flush
privileges
;
sql/sql_acl.cc
View file @
daf0345a
...
...
@@ -299,6 +299,7 @@ class ACL_DB :public ACL_ACCESS
public:
acl_host_and_ip
host
;
char
*
user
,
*
db
;
ulong
initial_access
;
/* access bits present in the table */
};
#ifndef NO_EMBEDDED_ACCESS_CHECKS
...
...
@@ -712,6 +713,7 @@ static my_bool acl_role_propagate_grants(ACL_ROLE *role,
void
*
not_used
__attribute__
((
unused
)));
static
int
add_role_user_mapping
(
ROLE_GRANT_PAIR
*
mapping
);
static
my_bool
get_role_access
(
ACL_ROLE
*
role
,
ulong
*
access
);
static
void
merge_role_grant_privileges
(
ACL_ROLE
*
target
,
ACL_ROLE
*
source
);
/*
Enumeration of various ACL's and Hashes used in handle_grant_struct()
...
...
@@ -1279,6 +1281,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
}
db
.
access
=
get_access
(
table
,
3
);
db
.
access
=
fix_rights_for_db
(
db
.
access
);
db
.
initial_access
=
db
.
access
;
if
(
lower_case_table_names
)
{
/*
...
...
@@ -2079,7 +2082,7 @@ static void acl_insert_user(const char *user, const char *host,
static
void
acl_update_db
(
const
char
*
user
,
const
char
*
host
,
const
char
*
db
,
ulong
privilege
s
)
ulong
privileges
,
bool
set_initial_acces
s
)
{
mysql_mutex_assert_owner
(
&
acl_cache
->
lock
);
...
...
@@ -2099,7 +2102,11 @@ static void acl_update_db(const char *user, const char *host, const char *db,
{
if
(
privileges
)
acl_db
->
access
=
privileges
;
{
acl_db
->
access
=
privileges
;
if
(
set_initial_access
)
acl_db
->
initial_access
=
acl_db
->
access
;
}
else
delete_dynamic_element
(
&
acl_dbs
,
i
);
}
...
...
@@ -2118,13 +2125,15 @@ static void acl_update_db(const char *user, const char *host, const char *db,
host Host name
db Database name
privileges Bitmap of privileges
set_initial_access If marked true, will set the initial_access field
to be set to the same value as privileges.
NOTES
acl_cache->lock must be locked when calling this
*/
static
void
acl_insert_db
(
const
char
*
user
,
const
char
*
host
,
const
char
*
db
,
ulong
privilege
s
)
ulong
privileges
,
bool
set_initial_acces
s
)
{
ACL_DB
acl_db
;
mysql_mutex_assert_owner
(
&
acl_cache
->
lock
);
...
...
@@ -2132,6 +2141,10 @@ static void acl_insert_db(const char *user, const char *host, const char *db,
update_hostname
(
&
acl_db
.
host
,
*
host
?
strdup_root
(
&
mem
,
host
)
:
0
);
acl_db
.
db
=
strdup_root
(
&
mem
,
db
);
acl_db
.
access
=
privileges
;
if
(
set_initial_access
)
acl_db
.
initial_access
=
acl_db
.
access
;
else
acl_db
.
initial_access
=
0
;
acl_db
.
sort
=
get_sort
(
3
,
acl_db
.
host
.
hostname
,
acl_db
.
db
,
acl_db
.
user
);
(
void
)
push_dynamic
(
&
acl_dbs
,(
uchar
*
)
&
acl_db
);
my_qsort
((
uchar
*
)
dynamic_element
(
&
acl_dbs
,
0
,
ACL_DB
*
),
acl_dbs
.
elements
,
...
...
@@ -2343,6 +2356,81 @@ my_bool acl_user_reset_grant(ACL_USER *user,
return
0
;
}
/*
The function merges access bits from a granted role to a grantee.
It creates data structures if they don't exist for the grantee.
This includes data structures related to database privileges, tables
privileges, column privileges, function and procedures privileges
*/
void
merge_role_grant_privileges
(
ACL_ROLE
*
target
,
ACL_ROLE
*
source
)
{
DBUG_ASSERT
(
source
->
flags
&
ROLE_GRANTS_FINAL
);
/* Merge global access rights */
target
->
access
|=
source
->
access
;
/* Merge database privileges */
DYNAMIC_ARRAY
target_dbs
,
source_dbs
;
/* arrays of pointers to ACL_DB elements */
ACL_DB
*
target_db
,
*
source_db
;
/* elements of the arrays */
(
void
)
my_init_dynamic_array
(
&
target_dbs
,
sizeof
(
ACL_DB
*
),
50
,
100
,
MYF
(
0
));
(
void
)
my_init_dynamic_array
(
&
source_dbs
,
sizeof
(
ACL_DB
*
),
50
,
100
,
MYF
(
0
));
/* get all acl_db elements for the source and the target */
for
(
uint
i
=
0
;
i
<
acl_dbs
.
elements
;
i
++
)
{
ACL_DB
*
acl_db
=
dynamic_element
(
&
acl_dbs
,
i
,
ACL_DB
*
);
if
(
acl_db
->
user
&&
!
acl_db
->
host
.
hostname
)
{
if
(
!
strcmp
(
target
->
user
.
str
,
acl_db
->
user
))
push_dynamic
(
&
target_dbs
,
(
uchar
*
)
&
acl_db
);
if
(
!
strcmp
(
source
->
user
.
str
,
acl_db
->
user
))
push_dynamic
(
&
source_dbs
,
(
uchar
*
)
&
acl_db
);
}
}
for
(
uint
i
=
0
;
i
<
source_dbs
.
elements
;
i
++
)
{
source_db
=
*
dynamic_element
(
&
source_dbs
,
i
,
ACL_DB
**
);
target_db
=
NULL
;
for
(
uint
j
=
0
;
j
<
target_dbs
.
elements
;
j
++
)
{
ACL_DB
*
acl_db
=
*
dynamic_element
(
&
target_dbs
,
i
,
ACL_DB
**
);
if
(
!
strcmp
(
source_db
->
db
,
acl_db
->
db
))
/* only need to compare DB here */
target_db
=
acl_db
;
}
/* acl_db element found for the target, only need to update acces bits */
if
(
target_db
)
{
target_db
->
access
|=
source_db
->
access
;
}
else
{
/*
Need to create an acl_db element as this role inherits database
privileges
*/
acl_insert_db
(
target
->
user
.
str
,
""
,
source_db
->
db
,
source_db
->
access
,
FALSE
);
}
}
delete_dynamic
(
&
source_dbs
);
delete_dynamic
(
&
target_dbs
);
/* Merge table privileges */
/* TODO */
/* Merge column privileges */
/* TODO */
/* Merge function and procedure privileges */
/* TODO */
}
/*
The function scans through all roles granted to the role passed as argument
and places the permissions in the access variable.
...
...
@@ -2380,7 +2468,7 @@ my_bool get_role_access(ACL_ROLE *role, ulong *access)
It uses a DYNAMIC_ARRAY to reduce the number of
malloc calls to a minimum
*/
DYNAMIC_ARRAY
stack
;
DYNAMIC_ARRAY
stack
;
NODE_STATE
state
;
/* variable used to insert elements in the stack */
state
.
neigh_idx
=
0
;
...
...
@@ -2427,7 +2515,7 @@ my_bool get_role_access(ACL_ROLE *role, ulong *access)
if
(
neighbour
->
flags
&
ROLE_GRANTS_FINAL
)
{
DBUG_PRINT
(
"info"
,
(
"Neighbour access is final, merging"
));
current
->
access
|=
neighbour
->
access
;
merge_role_grant_privileges
(
current
,
neighbour
)
;
continue
;
}
...
...
@@ -3474,10 +3562,10 @@ static int replace_db_table(TABLE *table, const char *db,
acl_cache
->
clear
(
1
);
// Clear privilege cache
if
(
old_row_exists
)
acl_update_db
(
combo
.
user
.
str
,
combo
.
host
.
str
,
db
,
rights
);
acl_update_db
(
combo
.
user
.
str
,
combo
.
host
.
str
,
db
,
rights
,
TRUE
);
else
if
(
rights
)
acl_insert_db
(
combo
.
user
.
str
,
combo
.
host
.
str
,
db
,
rights
);
acl_insert_db
(
combo
.
user
.
str
,
combo
.
host
.
str
,
db
,
rights
,
TRUE
);
DBUG_RETURN
(
0
);
/* This could only happen if the grant tables got corrupted */
...
...
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