Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
1790be14
Commit
1790be14
authored
Feb 07, 2019
by
antirez
Browse files
ACL: WIP: preserve the old config on loading errors.
parent
0f0240b5
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/acl.c
View file @
1790be14
...
@@ -90,6 +90,7 @@ struct ACLUserFlag {
...
@@ -90,6 +90,7 @@ struct ACLUserFlag {
void
ACLResetSubcommandsForCommand
(
user
*
u
,
unsigned
long
id
);
void
ACLResetSubcommandsForCommand
(
user
*
u
,
unsigned
long
id
);
void
ACLResetSubcommands
(
user
*
u
);
void
ACLResetSubcommands
(
user
*
u
);
void
ACLAddAllowedSubcommand
(
user
*
u
,
unsigned
long
id
,
const
char
*
sub
);
/* =============================================================================
/* =============================================================================
* Helper functions for the rest of the ACL implementation
* Helper functions for the rest of the ACL implementation
...
@@ -163,6 +164,11 @@ void ACLListFreeSds(void *item) {
...
@@ -163,6 +164,11 @@ void ACLListFreeSds(void *item) {
sdsfree
(
item
);
sdsfree
(
item
);
}
}
/* Method to duplicate list elements from ACL users password/ptterns lists. */
void
*
ACLListDupSds
(
void
*
item
)
{
return
sdsdup
(
item
);
}
/* Create a new user with the specified name, store it in the list
/* Create a new user with the specified name, store it in the list
* of users (the Users global radix tree), and returns a reference to
* of users (the Users global radix tree), and returns a reference to
* the structure representing the user.
* the structure representing the user.
...
@@ -178,8 +184,10 @@ user *ACLCreateUser(const char *name, size_t namelen) {
...
@@ -178,8 +184,10 @@ user *ACLCreateUser(const char *name, size_t namelen) {
u
->
patterns
=
listCreate
();
u
->
patterns
=
listCreate
();
listSetMatchMethod
(
u
->
passwords
,
ACLListMatchSds
);
listSetMatchMethod
(
u
->
passwords
,
ACLListMatchSds
);
listSetFreeMethod
(
u
->
passwords
,
ACLListFreeSds
);
listSetFreeMethod
(
u
->
passwords
,
ACLListFreeSds
);
listSetDupMethod
(
u
->
passwords
,
ACLListDupSds
);
listSetMatchMethod
(
u
->
patterns
,
ACLListMatchSds
);
listSetMatchMethod
(
u
->
patterns
,
ACLListMatchSds
);
listSetFreeMethod
(
u
->
patterns
,
ACLListFreeSds
);
listSetFreeMethod
(
u
->
patterns
,
ACLListFreeSds
);
listSetDupMethod
(
u
->
patterns
,
ACLListDupSds
);
memset
(
u
->
allowed_commands
,
0
,
sizeof
(
u
->
allowed_commands
));
memset
(
u
->
allowed_commands
,
0
,
sizeof
(
u
->
allowed_commands
));
raxInsert
(
Users
,(
unsigned
char
*
)
name
,
namelen
,
u
,
NULL
);
raxInsert
(
Users
,(
unsigned
char
*
)
name
,
namelen
,
u
,
NULL
);
return
u
;
return
u
;
...
@@ -212,6 +220,38 @@ void ACLFreeUser(user *u) {
...
@@ -212,6 +220,38 @@ void ACLFreeUser(user *u) {
zfree
(
u
);
zfree
(
u
);
}
}
/* Copy the user ACL rules from the source user 'src' to the destination
* user 'dst' so that at the end of the process they'll have exactly the
* same rules (but the names will continue to be the original ones). */
void
ACLCopyUser
(
user
*
dst
,
user
*
src
)
{
listRelease
(
dst
->
passwords
);
listRelease
(
dst
->
patterns
);
dst
->
passwords
=
listDup
(
src
->
passwords
);
dst
->
patterns
=
listDup
(
src
->
patterns
);
memcpy
(
dst
->
allowed_commands
,
src
->
allowed_commands
,
sizeof
(
dst
->
allowed_commands
));
dst
->
flags
=
src
->
flags
;
ACLResetSubcommands
(
dst
);
/* Copy the allowed subcommands array of array of SDS strings. */
if
(
src
->
allowed_subcommands
)
{
for
(
int
j
=
0
;
j
<
USER_COMMAND_BITS_COUNT
;
j
++
)
{
if
(
src
->
allowed_subcommands
[
j
])
{
for
(
int
i
=
0
;
src
->
allowed_subcommands
[
j
][
i
];
i
++
)
{
ACLAddAllowedSubcommand
(
dst
,
j
,
src
->
allowed_subcommands
[
j
][
i
]);
}
}
}
}
}
/* Free all the users registered in the radix tree 'users' and free the
* radix tree itself. */
void
ACLFreeUsersSet
(
rax
*
users
)
{
/* TODO */
}
/* Given a command ID, this function set by reference 'word' and 'bit'
/* Given a command ID, this function set by reference 'word' and 'bit'
* so that user->allowed_commands[word] will address the right word
* so that user->allowed_commands[word] will address the right word
* where the corresponding bit for the provided ID is stored, and
* where the corresponding bit for the provided ID is stored, and
...
@@ -1043,7 +1083,10 @@ int ACLLoadConfiguredUsers(void) {
...
@@ -1043,7 +1083,10 @@ int ACLLoadConfiguredUsers(void) {
* to avoid ending with broken rules if the ACL file is invalid for some
* to avoid ending with broken rules if the ACL file is invalid for some
* reason, so the function will attempt to validate the rules before loading
* reason, so the function will attempt to validate the rules before loading
* each user. For every line that will be found broken the function will
* each user. For every line that will be found broken the function will
* collect an error message. All the valid lines will be correctly processed.
* collect an error message.
*
* IMPORTANT: If there is at least a single error, nothing will be loaded
* and the rules will remain exactly as they were.
*
*
* At the end of the process, if no errors were found in the whole file then
* At the end of the process, if no errors were found in the whole file then
* NULL is returned. Otherwise an SDS string describing in a single line
* NULL is returned. Otherwise an SDS string describing in a single line
...
@@ -1075,6 +1118,14 @@ sds ACLLoadFromFile(const char *filename) {
...
@@ -1075,6 +1118,14 @@ sds ACLLoadFromFile(const char *filename) {
* to the real user mentioned in the ACL line. */
* to the real user mentioned in the ACL line. */
user
*
fakeuser
=
ACLCreateUnlinkedUser
();
user
*
fakeuser
=
ACLCreateUnlinkedUser
();
/* We do all the loading in a fresh insteance of the Users radix tree,
* so if there are errors loading the ACL file we can rollback to the
* old version. */
rax
*
old_users
=
Users
;
Users
=
raxNew
();
ACLInitDefaultUser
();
/* Load each line of the file. */
for
(
int
i
=
0
;
i
<
totlines
;
i
++
)
{
for
(
int
i
=
0
;
i
<
totlines
;
i
++
)
{
sds
*
argv
;
sds
*
argv
;
int
argc
;
int
argc
;
...
@@ -1147,11 +1198,24 @@ sds ACLLoadFromFile(const char *filename) {
...
@@ -1147,11 +1198,24 @@ sds ACLLoadFromFile(const char *filename) {
ACLFreeUser
(
fakeuser
);
ACLFreeUser
(
fakeuser
);
sdsfreesplitres
(
lines
,
totlines
);
sdsfreesplitres
(
lines
,
totlines
);
/* Chec if we found errors and react accordingly. */
if
(
sdslen
(
errors
)
==
0
)
{
if
(
sdslen
(
errors
)
==
0
)
{
/* The default user pointer is referenced in different places: instead
* of replacing such occurrences it is much simpler to copy the new
* default user configuration in the old one. */
user
*
new
=
ACLGetUserByName
(
"default"
,
7
);
ACLCopyUser
(
DefaultUser
,
new
);
ACLFreeUser
(
new
);
raxInsert
(
Users
,(
unsigned
char
*
)
"default"
,
7
,
DefaultUser
,
NULL
);
sdsfree
(
errors
);
sdsfree
(
errors
);
return
NULL
;
return
NULL
;
}
else
{
}
else
{
return
sdstrim
(
errors
,
" "
);
ACLFreeUsersSet
(
Users
);
Users
=
old_users
;
errors
=
sdscat
(
errors
,
"WARNING: ACL errors detected, no change to the previously active ACL rules was performed"
);
return
errors
;
}
}
}
}
...
...
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