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