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
058bbedc
Commit
058bbedc
authored
Feb 26, 2019
by
Madelyn Olson
Browse files
Add module APIs for custom authentication
parent
a15a5d70
Changes
9
Show 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