ACL -- show and modify the configuration of ACL users. * ACL HELP * ACL LOAD * ACL SAVE * ACL LIST * ACL USERS * ACL CAT [ ] * ACL SETUSER ... acl rules ... * ACL DELUSER [...] * ACL GETUSER * ACL GENPASS [ ] * ACL WHOAMI * ACL LOG [ | RESET] */
| 1890 | * ACL LOG [<count> | RESET] |
| 1891 | */ |
| 1892 | void aclCommand(client *c) { |
| 1893 | char *sub = c->argv[1]->ptr; |
| 1894 | if (!strcasecmp(sub,"setuser") && c->argc >= 3) { |
| 1895 | sds username = c->argv[2]->ptr; |
| 1896 | /* Check username validity. */ |
| 1897 | if (ACLStringHasSpaces(username,sdslen(username))) { |
| 1898 | addReplyErrorFormat(c, |
| 1899 | "Usernames can't contain spaces or null characters"); |
| 1900 | return; |
| 1901 | } |
| 1902 | |
| 1903 | /* Create a temporary user to validate and stage all changes against |
| 1904 | * before applying to an existing user or creating a new user. If all |
| 1905 | * arguments are valid the user parameters will all be applied together. |
| 1906 | * If there are any errors then none of the changes will be applied. */ |
| 1907 | user *tempu = ACLCreateUnlinkedUser(); |
| 1908 | user *u = ACLGetUserByName(username,sdslen(username)); |
| 1909 | if (u) ACLCopyUser(tempu, u); |
| 1910 | |
| 1911 | /* Initially redact all of the arguments to not leak any information |
| 1912 | * about the user. */ |
| 1913 | for (int j = 2; j < c->argc; j++) { |
| 1914 | redactClientCommandArgument(c, j); |
| 1915 | } |
| 1916 | |
| 1917 | for (int j = 3; j < c->argc; j++) { |
| 1918 | if (ACLSetUser(tempu,c->argv[j]->ptr,sdslen(c->argv[j]->ptr)) != C_OK) { |
| 1919 | const char *errmsg = ACLSetUserStringError(); |
| 1920 | addReplyErrorFormat(c, |
| 1921 | "Error in ACL SETUSER modifier '%s': %s", |
| 1922 | (char*)c->argv[j]->ptr, errmsg); |
| 1923 | |
| 1924 | ACLFreeUser(tempu); |
| 1925 | return; |
| 1926 | } |
| 1927 | } |
| 1928 | |
| 1929 | /* Existing pub/sub clients authenticated with the user may need to be |
| 1930 | * disconnected if (some of) their channel permissions were revoked. */ |
| 1931 | if (u && !(tempu->flags & USER_FLAG_ALLCHANNELS)) |
| 1932 | ACLKillPubsubClientsIfNeeded(u,tempu->channels); |
| 1933 | |
| 1934 | /* Overwrite the user with the temporary user we modified above. */ |
| 1935 | if (!u) u = ACLCreateUser(username,sdslen(username)); |
| 1936 | serverAssert(u != NULL); |
| 1937 | ACLCopyUser(u, tempu); |
| 1938 | ACLFreeUser(tempu); |
| 1939 | addReply(c,shared.ok); |
| 1940 | } else if (!strcasecmp(sub,"deluser") && c->argc >= 3) { |
| 1941 | int deleted = 0; |
| 1942 | for (int j = 2; j < c->argc; j++) { |
| 1943 | sds username = c->argv[j]->ptr; |
| 1944 | if (!strcmp(username,"default")) { |
| 1945 | addReplyError(c,"The 'default' user cannot be removed"); |
| 1946 | return; |
| 1947 | } |
| 1948 | } |
| 1949 |
nothing calls this directly
no test coverage detected