From c8391388c221b9255a7b6536c3f43438f36b8e2b Mon Sep 17 00:00:00 2001
From: antirez <antirez@gmail.com>
Date: Fri, 18 Jan 2019 11:49:30 +0100
Subject: [PATCH] ACL: remove server.requirepass + some refactoring.

---
 src/acl.c        | 10 ++++++++++
 src/config.c     | 10 ++++------
 src/networking.c |  2 +-
 src/sentinel.c   |  2 +-
 src/server.c     |  1 -
 src/server.h     |  4 ++--
 6 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/src/acl.c b/src/acl.c
index fc1edd87..a2cb8784 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -216,6 +216,16 @@ int ACLSetUser(user *u, const char *op, ssize_t oplen) {
     return C_OK;
 }
 
+/* Return the first password of the default user or NULL.
+ * This function is needed for backward compatibility with the old
+ * directive "requirepass" when Redis supported a single global
+ * password. */
+sds ACLDefaultUserFirstPassword(void) {
+    if (listLength(DefaultUser->passwords) == 0) return NULL;
+    listNode *first = listFirst(DefaultUser->passwords);
+    return listNodeValue(first);
+}
+
 /* Initialization of the ACL subsystem. */
 void ACLInit(void) {
     Users = raxNew();
diff --git a/src/config.c b/src/config.c
index de3cd012..ed3b6fec 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1581,9 +1581,8 @@ void configGetCommand(client *c) {
     }
     if (stringmatch(pattern,"requirepass",1)) {
         addReplyBulkCString(c,"requirepass");
-        if (listLength(DefaultUser->passwords)) {
-            listNode *first = listFirst(DefaultUser->passwords);
-            sds password = listNodeValue(first);
+        sds password = ACLDefaultUserFirstPassword();
+        if (password) {
             addReplyBulkCBuffer(c,password,sdslen(password));
         } else {
             addReplyBulkCString(c,"");
@@ -2004,18 +2003,17 @@ void rewriteConfigBindOption(struct rewriteConfigState *state) {
 void rewriteConfigRequirepassOption(struct rewriteConfigState *state, char *option) {
     int force = 1;
     sds line;
+    sds password = ACLDefaultUserFirstPassword();
 
     /* If there is no password set, we don't want the requirepass option
      * to be present in the configuration at all. */
-    if (listLength(DefaultUser->passwords) == 0) {
+    if (password == NULL) {
         rewriteConfigMarkAsProcessed(state,option);
         return;
     }
 
     line = sdsnew(option);
     line = sdscatlen(line, " ", 1);
-    listNode *first = listFirst(DefaultUser->passwords);
-    sds password = listNodeValue(first);
     line = sdscatsds(line, password);
 
     rewriteConfigRewriteLine(state,option,line,force);
diff --git a/src/networking.c b/src/networking.c
index 4aa19314..9e62cb6b 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -810,7 +810,7 @@ static void acceptCommonHandler(int fd, int flags, char *ip) {
      * user what to do to fix it if needed. */
     if (server.protected_mode &&
         server.bindaddr_count == 0 &&
-        server.requirepass == NULL &&
+        DefaultUser->flags & USER_FLAG_NOPASS &&
         !(flags & CLIENT_UNIX_SOCKET) &&
         ip != NULL)
     {
diff --git a/src/sentinel.c b/src/sentinel.c
index 1696b121..4d03c9c1 100644
--- a/src/sentinel.c
+++ b/src/sentinel.c
@@ -1961,7 +1961,7 @@ void sentinelSendAuthIfNeeded(sentinelRedisInstance *ri, redisAsyncContext *c) {
     } else if (ri->flags & SRI_SLAVE) {
         auth_pass = ri->master->auth_pass;
     } else if (ri->flags & SRI_SENTINEL) {
-        if (server.requirepass) auth_pass = server.requirepass;
+        auth_pass = ACLDefaultUserFirstPassword();
     }
 
     if (auth_pass) {
diff --git a/src/server.c b/src/server.c
index 37757b21..41d6f454 100644
--- a/src/server.c
+++ b/src/server.c
@@ -1596,7 +1596,6 @@ void initServerConfig(void) {
     server.pidfile = NULL;
     server.rdb_filename = zstrdup(CONFIG_DEFAULT_RDB_FILENAME);
     server.aof_filename = zstrdup(CONFIG_DEFAULT_AOF_FILENAME);
-    server.requirepass = NULL;
     server.rdb_compression = CONFIG_DEFAULT_RDB_COMPRESSION;
     server.rdb_checksum = CONFIG_DEFAULT_RDB_CHECKSUM;
     server.stop_writes_on_bgsave_err = CONFIG_DEFAULT_STOP_WRITES_ON_BGSAVE_ERROR;
diff --git a/src/server.h b/src/server.h
index 3021633b..956494aa 100644
--- a/src/server.h
+++ b/src/server.h
@@ -778,7 +778,7 @@ typedef struct client {
     time_t lastinteraction; /* Time of the last interaction, used for timeout */
     time_t obuf_soft_limit_reached_time;
     int flags;              /* Client flags: CLIENT_* macros. */
-    int authenticated;      /* When requirepass is non-NULL. */
+    int authenticated;      /* Needed when the default user requires auth. */
     int replstate;          /* Replication state if this is a slave. */
     int repl_put_online_on_ack; /* Install slave write handler on ACK. */
     int repldbfd;           /* Replication DB file descriptor. */
@@ -988,7 +988,6 @@ struct redisServer {
     int shutdown_asap;          /* SHUTDOWN needed ASAP */
     int activerehashing;        /* Incremental rehash in serverCron() */
     int active_defrag_running;  /* Active defragmentation running (holds current scan aggressiveness) */
-    char *requirepass;          /* Pass for AUTH command, or NULL */
     char *pidfile;              /* PID file path */
     int arch_bits;              /* 32 or 64 depending on sizeof(long) */
     int cronloops;              /* Number of times the cron function run */
@@ -1707,6 +1706,7 @@ unsigned long ACLGetCommandID(const char *cmdname);
 user *ACLGetUserByName(const char *name, size_t namelen);
 int ACLCheckCommandPerm(client *c);
 int ACLSetUser(user *u, const char *op, ssize_t oplen);
+sds ACLDefaultUserFirstPassword(void);
 
 /* Sorted sets data type */