Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
058bbedc
Commit
058bbedc
authored
Feb 26, 2019
by
Madelyn Olson
Browse files
Add module APIs for custom authentication
parent
a15a5d70
Changes
9
Hide whitespace changes
Inline
Side-by-side
src/acl.c
View file @
058bbedc
...
...
@@ -975,6 +975,7 @@ int ACLAuthenticateUser(client *c, robj *username, robj *password) {
if
(
ACLCheckUserCredentials
(
username
,
password
)
==
C_OK
)
{
c
->
authenticated
=
1
;
c
->
user
=
ACLGetUserByName
(
username
->
ptr
,
sdslen
(
username
->
ptr
));
moduleNotifyUserChanged
(
c
);
return
C_OK
;
}
else
{
return
C_ERR
;
...
...
src/module.c
View file @
058bbedc
...
...
@@ -349,6 +349,22 @@ list *RedisModule_EventListeners; /* Global list of all the active events. */
unsigned
long
long
ModulesInHooks
=
0
;
/* Total number of modules in hooks
callbacks right now. */
/* Data structures related to the redis module users */
typedef
void
(
*
RedisModuleUserChangedFunc
)
(
void
*
privdata
);
typedef
struct
RedisModuleUser
{
user
*
user
;
/* Reference to the real redis user */
}
RedisModuleUser
;
typedef
struct
RedisModuleAuthCtx
{
RedisModuleUserChangedFunc
callback
;
/* Callback when user is changed or
/* deleted. */
void
*
privdata
;
/* Private data for the callback */
client
*
authenticated_client
;
/* A reference to client that was
/* authenticated */
}
RedisModuleAuthCtx
;
/* --------------------------------------------------------------------------
* Prototypes
* -------------------------------------------------------------------------- */
...
...
@@ -711,6 +727,7 @@ int commandFlagsFromString(char *s) {
else
if
(
!
strcasecmp
(
t
,
"allow-stale"
))
flags
|=
CMD_STALE
;
else
if
(
!
strcasecmp
(
t
,
"no-monitor"
))
flags
|=
CMD_SKIP_MONITOR
;
else
if
(
!
strcasecmp
(
t
,
"fast"
))
flags
|=
CMD_FAST
;
else
if
(
!
strcasecmp
(
t
,
"no-auth"
))
flags
|=
CMD_NO_AUTH
;
else
if
(
!
strcasecmp
(
t
,
"getkeys-api"
))
flags
|=
CMD_MODULE_GETKEYS
;
else
if
(
!
strcasecmp
(
t
,
"no-cluster"
))
flags
|=
CMD_MODULE_NO_CLUSTER
;
else
break
;
...
...
@@ -772,6 +789,9 @@ int commandFlagsFromString(char *s) {
* example, is unable to report the position of the
* keys, programmatically creates key names, or any
* other reason.
* * **"no-auth"**: This command can be run by an un-authenticated client.
* Normally this is used by a command that is used
* to authenticate a client.
*/
int
RM_CreateCommand
(
RedisModuleCtx
*
ctx
,
const
char
*
name
,
RedisModuleCmdFunc
cmdfunc
,
const
char
*
strflags
,
int
firstkey
,
int
lastkey
,
int
keystep
)
{
int
flags
=
strflags
?
commandFlagsFromString
((
char
*
)
strflags
)
:
0
;
...
...
@@ -5108,6 +5128,113 @@ int RM_GetTimerInfo(RedisModuleCtx *ctx, RedisModuleTimerID id, uint64_t *remain
return
REDISMODULE_OK
;
}
/* --------------------------------------------------------------------------
* Modules ACL API
*
* Implements a hook into the authentication and authorization within Redis.
* --------------------------------------------------------------------------*/
/* This function is called when a clients user has changed, since a module
* may be tracking extra meta data about the client. This is also called
* when a client is deleted. */
void
moduleNotifyUserChanged
(
client
*
c
)
{
RedisModuleAuthCtx
*
auth_ctx
=
(
RedisModuleAuthCtx
*
)
c
->
auth_ctx
;
if
(
auth_ctx
)
{
auth_ctx
->
callback
(
auth_ctx
->
privdata
);
zfree
(
auth_ctx
);
}
}
static
int
authenticateClientWithUser
(
RedisModuleCtx
*
ctx
,
user
*
user
,
RedisModuleAuthCtx
*
auth_ctx
)
{
if
(
auth_ctx
&&
auth_ctx
->
authenticated_client
)
{
/* Prevent basic misuse of Auth contexts */
return
REDISMODULE_ERR
;
}
if
(
user
->
flags
&
USER_FLAG_DISABLED
)
{
return
REDISMODULE_ERR
;
}
moduleNotifyUserChanged
(
ctx
->
client
);
ctx
->
client
->
user
=
user
;
ctx
->
client
->
authenticated
=
1
;
if
(
auth_ctx
)
{
ctx
->
client
->
auth_ctx
=
auth_ctx
;
auth_ctx
->
authenticated_client
=
ctx
->
client
;
}
return
REDISMODULE_OK
;
}
/* Creates a new user that is unlinked from the main ACL user dictionary. These
* users behave the same way as those in ACL.c except for a few minor
* differences. These users do not exist within a namespace, and handling
* duplicate users is the responsibility of the calling module. These users are
* also not attached to the redis users dictionary, so they are not returned
* via ACL LIST or GETUSER. This also means that users created here must be
* updated with the SetUserACL function instead of through ACL SETUSER. */
RedisModuleUser
*
RM_CreateModuleUser
(
const
char
*
name
)
{
RedisModuleUser
*
new_user
=
zmalloc
(
sizeof
(
RedisModuleUser
));
new_user
->
user
=
ACLCreateUnlinkedUser
();
/* Free the previous temporarily assigned name to assign the new one */
sdsfree
(
new_user
->
user
->
name
);
new_user
->
user
->
name
=
sdsnew
(
name
);
return
new_user
;
}
/* Frees a given user and disconnects all of the clients that have been
* authenticated with it. */
int
RM_FreeModuleUser
(
RedisModuleUser
*
user
)
{
ACLFreeUserAndKillClients
(
user
->
user
);
zfree
(
user
);
return
REDISMODULE_OK
;
}
/* Sets the user permission of a user created through the redis module
* interface. The syntax is the sam as ACL SETUSER, so refer to the
* documentation in acl.c for more information. */
int
RM_SetModuleUserACL
(
RedisModuleUser
*
user
,
const
char
*
acl
)
{
return
ACLSetUser
(
user
->
user
,
acl
,
-
1
);
}
/* Authenticate the current contexts user with the provided module user.
* Throws an error if the user is disabled or the AuthCtx is misued */
int
RM_AuthenticateClientWithUser
(
RedisModuleCtx
*
ctx
,
RedisModuleUser
*
module_user
,
RedisModuleAuthCtx
*
auth_ctx
)
{
return
authenticateClientWithUser
(
ctx
,
module_user
->
user
,
auth_ctx
);
}
/* Authenticate the current contexts user with the provided redis acl user.
* Throws an error if the user is disabled, the user doesn't exit,
* or the AuthCtx is misused. */
int
RM_AuthenticateClientWithACLUser
(
RedisModuleCtx
*
ctx
,
const
char
*
name
,
size_t
len
,
RedisModuleAuthCtx
*
auth_ctx
)
{
user
*
acl_user
=
ACLGetUserByName
(
name
,
len
);
if
(
!
acl_user
)
{
return
REDISMODULE_ERR
;
}
return
authenticateClientWithUser
(
ctx
,
acl_user
,
auth_ctx
);
}
/* Create a redis Auth Ctx which can be used to notify the module when
* the client authenticates with a different user or to revoke access
* to the authenticated client. */
RedisModuleAuthCtx
*
RM_CreateAuthCtx
(
RedisModuleUserChangedFunc
callback
,
void
*
privdata
)
{
RedisModuleAuthCtx
*
auth_ctx
=
zmalloc
(
sizeof
(
RedisModuleAuthCtx
));
auth_ctx
->
callback
=
callback
;
auth_ctx
->
privdata
=
privdata
;
return
auth_ctx
;
}
/* Revokes the authentication that was granted during the specified
* AuthCtx. The method is not thread safe. */
void
RM_RevokeAuthentication
(
RedisModuleAuthCtx
*
ctx
)
{
/* Revoking authentication frees the client today. */
freeClientAsync
(
ctx
->
authenticated_client
);
}
/* --------------------------------------------------------------------------
* Modules Dictionary API
*
...
...
@@ -6971,4 +7098,12 @@ void moduleRegisterCoreAPI(void) {
REGISTER_API
(
BlockClientOnKeys
);
REGISTER_API
(
SignalKeyAsReady
);
REGISTER_API
(
GetBlockedClientReadyKey
);
REGISTER_API
(
CreateModuleUser
);
REGISTER_API
(
SetModuleUserACL
);
REGISTER_API
(
FreeModuleUser
);
REGISTER_API
(
RevokeAuthentication
);
REGISTER_API
(
CreateAuthCtx
);
REGISTER_API
(
AuthenticateClientWithACLUser
);
REGISTER_API
(
AuthenticateClientWithUser
);
}
src/modules/Makefile
View file @
058bbedc
...
...
@@ -13,7 +13,7 @@ endif
.SUFFIXES
:
.c .so .xo .o
all
:
helloworld.so hellotype.so helloblock.so testmodule.so hellocluster.so hellotimer.so hellodict.so hellohook.so
all
:
helloworld.so hellotype.so helloblock.so testmodule.so hellocluster.so hellotimer.so hellodict.so hellohook.so
helloacl.so
.c.xo
:
$(CC)
-I
.
$(CFLAGS)
$(SHOBJ_CFLAGS)
-fPIC
-c
$<
-o
$@
...
...
@@ -53,6 +53,11 @@ hellohook.xo: ../redismodule.h
hellohook.so
:
hellohook.xo
$(LD)
-o
$@
$<
$(SHOBJ_LDFLAGS)
$(LIBS)
-lc
helloacl.xo
:
../redismodule.h
helloacl.so
:
helloacl.xo
$(LD)
-o
$@
$<
$(SHOBJ_LDFLAGS)
$(LIBS)
-lc
testmodule.xo
:
../redismodule.h
testmodule.so
:
testmodule.xo
...
...
src/modules/helloacl.c
0 → 100644
View file @
058bbedc
/* ACL API example - An example of performing custom password authentication
*
* -----------------------------------------------------------------------------
*
* Copyright 2019 Amazon.com, Inc. or its affiliates.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#define REDISMODULE_EXPERIMENTAL_API
#include "../redismodule.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <pthread.h>
#include <unistd.h>
// A simple global user
static
RedisModuleUser
*
global
;
static
RedisModuleAuthCtx
*
global_auth_ctx
;
/* HELLOACL.REVOKE
* Synchronously revoke access from a user. */
int
RevokeCommand_RedisCommand
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argc
);
if
(
global_auth_ctx
)
{
RedisModule_RevokeAuthentication
(
global_auth_ctx
);
return
RedisModule_ReplyWithSimpleString
(
ctx
,
"OK"
);
}
else
{
return
RedisModule_ReplyWithError
(
ctx
,
"Global user currently not used"
);
}
}
/* HELLOACL.RESET
* Synchronously delete and re-create a module user. */
int
ResetCommand_RedisCommand
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argc
);
RedisModule_FreeModuleUser
(
global
);
global
=
RedisModule_CreateModuleUser
(
"global"
);
RedisModule_SetModuleUserACL
(
global
,
"allcommands"
);
RedisModule_SetModuleUserACL
(
global
,
"allkeys"
);
RedisModule_SetModuleUserACL
(
global
,
"on"
);
return
RedisModule_ReplyWithSimpleString
(
ctx
,
"OK"
);
}
/* Callback handler for user changes, use this to notify a module of
* changes to users authenticated by the module */
void
HelloACL_UserChanged
(
void
*
privdata
)
{
REDISMODULE_NOT_USED
(
privdata
);
global_auth_ctx
=
NULL
;
}
/* HELLOACL.AUTHGLOBAL
* Synchronously assigns a module user to the current context. */
int
AuthGlobalCommand_RedisCommand
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argc
);
if
(
global_auth_ctx
)
{
return
RedisModule_ReplyWithError
(
ctx
,
"Global user currently used"
);
}
RedisModuleAuthCtx
*
auth_ctx
=
RedisModule_CreateAuthCtx
(
HelloACL_UserChanged
,
NULL
);
RedisModule_AuthenticateClientWithUser
(
ctx
,
global
,
auth_ctx
);
global_auth_ctx
=
auth_ctx
;
return
RedisModule_ReplyWithSimpleString
(
ctx
,
"OK"
);
}
#define TIMEOUT_TIME 1000
/* Reply callback for auth command HELLOACL.AUTHASYNC */
int
HelloACL_Reply
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argc
);
size_t
length
;
RedisModuleString
*
user_string
=
RedisModule_GetBlockedClientPrivateData
(
ctx
);
const
char
*
name
=
RedisModule_StringPtrLen
(
user_string
,
&
length
);
if
(
RedisModule_AuthenticateClientWithACLUser
(
ctx
,
name
,
length
,
NULL
)
==
REDISMODULE_ERR
)
{
return
RedisModule_ReplyWithError
(
ctx
,
"Invalid Username or password"
);
}
return
RedisModule_ReplyWithSimpleString
(
ctx
,
"OK"
);
}
/* Timeout callback for auth command HELLOACL.AUTHASYNC */
int
HelloACL_Timeout
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argc
);
return
RedisModule_ReplyWithSimpleString
(
ctx
,
"Request timedout"
);
}
/* Private data frees data for HELLOACL.AUTHASYNC command. */
void
HelloACL_FreeData
(
RedisModuleCtx
*
ctx
,
void
*
privdata
)
{
REDISMODULE_NOT_USED
(
ctx
);
RedisModule_FreeString
(
NULL
,
privdata
);
}
/* Background authentication can happen here. */
void
*
HelloACL_ThreadMain
(
void
*
args
)
{
void
**
targs
=
args
;
RedisModuleBlockedClient
*
bc
=
targs
[
0
];
RedisModuleString
*
user
=
targs
[
1
];
RedisModule_Free
(
targs
);
RedisModule_UnblockClient
(
bc
,
user
);
return
NULL
;
}
/* HELLOACL.AUTHASYNC
* Asynchronously assigns an ACL user to the current context. */
*/
int
AuthAsyncCommand_RedisCommand
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
if
(
argc
!=
2
)
return
RedisModule_WrongArity
(
ctx
);
pthread_t
tid
;
RedisModuleBlockedClient
*
bc
=
RedisModule_BlockClient
(
ctx
,
HelloACL_Reply
,
HelloACL_Timeout
,
HelloACL_FreeData
,
TIMEOUT_TIME
);
void
**
targs
=
RedisModule_Alloc
(
sizeof
(
void
*
)
*
2
);
targs
[
0
]
=
bc
;
targs
[
1
]
=
RedisModule_CreateStringFromString
(
NULL
,
argv
[
1
]);
if
(
pthread_create
(
&
tid
,
NULL
,
HelloACL_ThreadMain
,
targs
)
!=
0
)
{
RedisModule_AbortBlock
(
bc
);
return
RedisModule_ReplyWithError
(
ctx
,
"-ERR Can't start thread"
);
}
return
REDISMODULE_OK
;
}
/* This function must be present on each Redis module. It is used in order to
* register the commands into the Redis server. */
int
RedisModule_OnLoad
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argc
);
if
(
RedisModule_Init
(
ctx
,
"helloacl"
,
1
,
REDISMODULE_APIVER_1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"helloacl.reset"
,
ResetCommand_RedisCommand
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"helloacl.revoke"
,
RevokeCommand_RedisCommand
,
""
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"helloacl.authglobal"
,
AuthGlobalCommand_RedisCommand
,
"no-auth"
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"helloacl.authasync"
,
AuthAsyncCommand_RedisCommand
,
"no-auth"
,
0
,
0
,
0
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
global
=
RedisModule_CreateModuleUser
(
"global"
);
RedisModule_SetModuleUserACL
(
global
,
"allcommands"
);
RedisModule_SetModuleUserACL
(
global
,
"allkeys"
);
RedisModule_SetModuleUserACL
(
global
,
"on"
);
global_auth_ctx
=
NULL
;
return
REDISMODULE_OK
;
}
src/networking.c
View file @
058bbedc
...
...
@@ -154,6 +154,7 @@ client *createClient(connection *conn) {
c
->
peerid
=
NULL
;
c
->
client_list_node
=
NULL
;
c
->
client_tracking_redirection
=
0
;
c
->
auth_ctx
=
NULL
;
listSetFreeMethod
(
c
->
pubsub_patterns
,
decrRefCountVoid
);
listSetMatchMethod
(
c
->
pubsub_patterns
,
listMatchObjects
);
if
(
conn
)
linkClient
(
c
);
...
...
@@ -1051,6 +1052,9 @@ void freeClient(client *c) {
c
);
}
/* Notify module system that this client auth status changed. */
moduleNotifyUserChanged
(
c
);
/* If it is our master that's beging disconnected we should make sure
* to cache the state to try a partial resynchronization later.
*
...
...
src/redismodule.h
View file @
058bbedc
...
...
@@ -392,6 +392,8 @@ typedef struct RedisModuleDictIter RedisModuleDictIter;
typedef
struct
RedisModuleCommandFilterCtx
RedisModuleCommandFilterCtx
;
typedef
struct
RedisModuleCommandFilter
RedisModuleCommandFilter
;
typedef
struct
RedisModuleInfoCtx
RedisModuleInfoCtx
;
typedef
struct
RedisModuleUser
RedisModuleUser
;
typedef
struct
RedisModuleAuthCtx
RedisModuleAuthCtx
;
typedef
int
(
*
RedisModuleCmdFunc
)(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
);
typedef
void
(
*
RedisModuleDisconnectFunc
)(
RedisModuleCtx
*
ctx
,
RedisModuleBlockedClient
*
bc
);
...
...
@@ -409,6 +411,7 @@ typedef void (*RedisModuleTimerProc)(RedisModuleCtx *ctx, void *data);
typedef
void
(
*
RedisModuleCommandFilterFunc
)
(
RedisModuleCommandFilterCtx
*
filter
);
typedef
void
(
*
RedisModuleForkDoneHandler
)
(
int
exitcode
,
int
bysignal
,
void
*
user_data
);
typedef
void
(
*
RedisModuleInfoFunc
)(
RedisModuleInfoCtx
*
ctx
,
int
for_crash_report
);
typedef
void
(
*
RedisModuleUserChangedFunc
)(
void
*
privdata
);
#define REDISMODULE_TYPE_METHOD_VERSION 2
typedef
struct
RedisModuleTypeMethods
{
...
...
@@ -633,6 +636,13 @@ int REDISMODULE_API_FUNC(RedisModule_CommandFilterArgDelete)(RedisModuleCommandF
int
REDISMODULE_API_FUNC
(
RedisModule_Fork
)(
RedisModuleForkDoneHandler
cb
,
void
*
user_data
);
int
REDISMODULE_API_FUNC
(
RedisModule_ExitFromChild
)(
int
retcode
);
int
REDISMODULE_API_FUNC
(
RedisModule_KillForkChild
)(
int
child_pid
);
RedisModuleUser
*
REDISMODULE_API_FUNC
(
RedisModule_CreateModuleUser
)(
const
char
*
name
);
void
REDISMODULE_API_FUNC
(
RedisModule_FreeModuleUser
)(
RedisModuleUser
*
user
);
int
REDISMODULE_API_FUNC
(
RedisModule_SetModuleUserACL
)(
RedisModuleUser
*
user
,
const
char
*
acl
);
int
REDISMODULE_API_FUNC
(
RedisModule_AuthenticateClientWithACLUser
)(
RedisModuleCtx
*
ctx
,
const
char
*
name
,
size_t
len
,
RedisModuleAuthCtx
*
auth_ctx
);
int
REDISMODULE_API_FUNC
(
RedisModule_AuthenticateClientWithUser
)(
RedisModuleCtx
*
ctx
,
RedisModuleUser
*
module_user
,
RedisModuleAuthCtx
*
auth_ctx
);
void
REDISMODULE_API_FUNC
(
RedisModule_RevokeAuthentication
)(
RedisModuleAuthCtx
*
ctx
);
RedisModuleAuthCtx
*
REDISMODULE_API_FUNC
(
RedisModule_CreateAuthCtx
)(
RedisModuleUserChangedFunc
callback
,
void
*
privdata
);
#endif
#define RedisModule_IsAOFClient(id) ((id) == UINT64_MAX)
...
...
@@ -842,6 +852,14 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
Fork
);
REDISMODULE_GET_API
(
ExitFromChild
);
REDISMODULE_GET_API
(
KillForkChild
);
REDISMODULE_GET_API
(
CreateModuleUser
);
REDISMODULE_GET_API
(
FreeModuleUser
);
REDISMODULE_GET_API
(
SetModuleUserACL
);
REDISMODULE_GET_API
(
RevokeAuthentication
);
REDISMODULE_GET_API
(
CreateAuthCtx
);
REDISMODULE_GET_API
(
AuthenticateClientWithACLUser
);
REDISMODULE_GET_API
(
AuthenticateClientWithUser
);
#endif
if
(
RedisModule_IsModuleNameBusy
&&
RedisModule_IsModuleNameBusy
(
name
))
return
REDISMODULE_ERR
;
...
...
src/sentinel.c
View file @
058bbedc
...
...
@@ -461,8 +461,8 @@ struct redisCommand sentinelcmds[] = {
{
"role"
,
sentinelRoleCommand
,
1
,
"ok-loading"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
},
{
"client"
,
clientCommand
,
-
2
,
"read-only no-script"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
},
{
"shutdown"
,
shutdownCommand
,
-
1
,
""
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
},
{
"auth"
,
authCommand
,
2
,
"no-script ok-loading ok-stale fast"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
},
{
"hello"
,
helloCommand
,
-
2
,
"no-script fast"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
}
{
"auth"
,
authCommand
,
2
,
"
no-auth
no-script ok-loading ok-stale fast"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
},
{
"hello"
,
helloCommand
,
-
2
,
"
no-auth
no-script fast"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
}
};
/* This function overwrites a few normal Redis config default with Sentinel
...
...
src/server.c
View file @
058bbedc
...
...
@@ -629,7 +629,7 @@ struct redisCommand redisCommandTable[] = {
0
,
NULL
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"auth"
,
authCommand
,
-
2
,
"no-script ok-loading ok-stale fast no-monitor no-slowlog @connection"
,
"
no-auth
no-script ok-loading ok-stale fast no-monitor no-slowlog @connection"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
,
0
},
/* We don't allow PING during loading since in Redis PING is used as
...
...
@@ -824,7 +824,7 @@ struct redisCommand redisCommandTable[] = {
0
,
NULL
,
0
,
0
,
0
,
0
,
0
,
0
},
{
"hello"
,
helloCommand
,
-
2
,
"no-script fast no-monitor no-slowlog @connection"
,
"
no-auth
no-script fast no-monitor no-slowlog @connection"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
,
0
},
/* EVAL can modify the dataset, however it is not flagged as a write
...
...
@@ -3008,6 +3008,8 @@ int populateCommandTableParseFlags(struct redisCommand *c, char *strflags) {
c
->
flags
|=
CMD_ASKING
;
}
else
if
(
!
strcasecmp
(
flag
,
"fast"
))
{
c
->
flags
|=
CMD_FAST
|
CMD_CATEGORY_FAST
;
}
else
if
(
!
strcasecmp
(
flag
,
"no-auth"
))
{
c
->
flags
|=
CMD_NO_AUTH
;
}
else
{
/* Parse ACL categories here if the flag name starts with @. */
uint64_t
catflag
;
...
...
@@ -3423,8 +3425,9 @@ int processCommand(client *c) {
DefaultUser
->
flags
&
USER_FLAG_DISABLED
)
&&
!
c
->
authenticated
;
if
(
auth_required
)
{
/* AUTH and HELLO are valid even in non authenticated state. */
if
(
c
->
cmd
->
proc
!=
authCommand
&&
c
->
cmd
->
proc
!=
helloCommand
)
{
/* AUTH and HELLO and no auth modules are valid even in
* non-authenticated state. */
if
(
!
(
c
->
cmd
->
flags
&
CMD_NO_AUTH
))
{
flagTransaction
(
c
);
addReply
(
c
,
shared
.
noautherr
);
return
C_OK
;
...
...
src/server.h
View file @
058bbedc
...
...
@@ -237,33 +237,34 @@ typedef long long mstime_t; /* millisecond time type. */
#define CMD_SKIP_SLOWLOG (1ULL<<12)
/* "no-slowlog" flag */
#define CMD_ASKING (1ULL<<13)
/* "cluster-asking" flag */
#define CMD_FAST (1ULL<<14)
/* "fast" flag */
#define CMD_NO_AUTH (1ULL<<15)
/* "no-auth" flag */
/* Command flags used by the module system. */
#define CMD_MODULE_GETKEYS (1ULL<<1
5
)
/* Use the modules getkeys interface. */
#define CMD_MODULE_NO_CLUSTER (1ULL<<1
6
)
/* Deny on Redis Cluster. */
#define CMD_MODULE_GETKEYS (1ULL<<1
6
)
/* Use the modules getkeys interface. */
#define CMD_MODULE_NO_CLUSTER (1ULL<<1
7
)
/* Deny on Redis Cluster. */
/* Command flags that describe ACLs categories. */
#define CMD_CATEGORY_KEYSPACE (1ULL<<1
7
)
#define CMD_CATEGORY_READ (1ULL<<1
8
)
#define CMD_CATEGORY_WRITE (1ULL<<
19
)
#define CMD_CATEGORY_SET (1ULL<<2
0
)
#define CMD_CATEGORY_SORTEDSET (1ULL<<2
1
)
#define CMD_CATEGORY_LIST (1ULL<<2
2
)
#define CMD_CATEGORY_HASH (1ULL<<2
3
)
#define CMD_CATEGORY_STRING (1ULL<<2
4
)
#define CMD_CATEGORY_BITMAP (1ULL<<2
5
)
#define CMD_CATEGORY_HYPERLOGLOG (1ULL<<2
6
)
#define CMD_CATEGORY_GEO (1ULL<<2
7
)
#define CMD_CATEGORY_STREAM (1ULL<<2
8
)
#define CMD_CATEGORY_PUBSUB (1ULL<<
29
)
#define CMD_CATEGORY_ADMIN (1ULL<<3
0
)
#define CMD_CATEGORY_FAST (1ULL<<3
1
)
#define CMD_CATEGORY_SLOW (1ULL<<3
2
)
#define CMD_CATEGORY_BLOCKING (1ULL<<3
3
)
#define CMD_CATEGORY_DANGEROUS (1ULL<<3
4
)
#define CMD_CATEGORY_CONNECTION (1ULL<<3
5
)
#define CMD_CATEGORY_TRANSACTION (1ULL<<3
6
)
#define CMD_CATEGORY_SCRIPTING (1ULL<<3
7
)
#define CMD_CATEGORY_KEYSPACE (1ULL<<1
8
)
#define CMD_CATEGORY_READ (1ULL<<1
9
)
#define CMD_CATEGORY_WRITE (1ULL<<
20
)
#define CMD_CATEGORY_SET (1ULL<<2
1
)
#define CMD_CATEGORY_SORTEDSET (1ULL<<2
2
)
#define CMD_CATEGORY_LIST (1ULL<<2
3
)
#define CMD_CATEGORY_HASH (1ULL<<2
4
)
#define CMD_CATEGORY_STRING (1ULL<<2
5
)
#define CMD_CATEGORY_BITMAP (1ULL<<2
6
)
#define CMD_CATEGORY_HYPERLOGLOG (1ULL<<2
7
)
#define CMD_CATEGORY_GEO (1ULL<<2
8
)
#define CMD_CATEGORY_STREAM (1ULL<<2
9
)
#define CMD_CATEGORY_PUBSUB (1ULL<<
30
)
#define CMD_CATEGORY_ADMIN (1ULL<<3
1
)
#define CMD_CATEGORY_FAST (1ULL<<3
2
)
#define CMD_CATEGORY_SLOW (1ULL<<3
3
)
#define CMD_CATEGORY_BLOCKING (1ULL<<3
4
)
#define CMD_CATEGORY_DANGEROUS (1ULL<<3
5
)
#define CMD_CATEGORY_CONNECTION (1ULL<<3
6
)
#define CMD_CATEGORY_TRANSACTION (1ULL<<3
7
)
#define CMD_CATEGORY_SCRIPTING (1ULL<<3
8
)
/* AOF states */
#define AOF_OFF 0
/* AOF is off */
...
...
@@ -892,6 +893,7 @@ typedef struct client {
list
*
pubsub_patterns
;
/* patterns a client is interested in (SUBSCRIBE) */
sds
peerid
;
/* Cached peer ID. */
listNode
*
client_list_node
;
/* list node in client list */
void
*
auth_ctx
;
/* Structured used to track module authentication */
/* If this client is in tracking mode and this field is non zero,
* invalidation messages for keys fetched by this client will be send to
...
...
@@ -1606,6 +1608,7 @@ void processModuleLoadingProgressEvent(int is_aof);
int
moduleTryServeClientBlockedOnKey
(
client
*
c
,
robj
*
key
);
void
moduleUnblockClient
(
client
*
c
);
int
moduleClientIsBlockedOnKeys
(
client
*
c
);
void
moduleNotifyUserChanged
(
client
*
c
);
/* Utils */
long
long
ustime
(
void
);
...
...
@@ -1899,6 +1902,8 @@ int ACLLoadConfiguredUsers(void);
sds
ACLDescribeUser
(
user
*
u
);
void
ACLLoadUsersAtStartup
(
void
);
void
addReplyCommandCategories
(
client
*
c
,
struct
redisCommand
*
cmd
);
user
*
ACLCreateUnlinkedUser
();
void
ACLFreeUserAndKillClients
(
user
*
u
);
/* Sorted sets data type */
...
...
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