Check the username and password pair and return C_OK if they are valid, * otherwise C_ERR is returned and errno is set to: * * EINVAL: if the username-password do not match. * ENONENT: if the specified user does not exist at all. */
| 1066 | * ENONENT: if the specified user does not exist at all. |
| 1067 | */ |
| 1068 | int ACLCheckUserCredentials(robj *username, robj *password) { |
| 1069 | user *u = ACLGetUserByName(username->ptr,sdslen(username->ptr)); |
| 1070 | if (u == NULL) { |
| 1071 | errno = ENOENT; |
| 1072 | return C_ERR; |
| 1073 | } |
| 1074 | |
| 1075 | /* Disabled users can't login. */ |
| 1076 | if (u->flags & USER_FLAG_DISABLED) { |
| 1077 | errno = EINVAL; |
| 1078 | return C_ERR; |
| 1079 | } |
| 1080 | |
| 1081 | /* If the user is configured to don't require any password, we |
| 1082 | * are already fine here. */ |
| 1083 | if (u->flags & USER_FLAG_NOPASS) return C_OK; |
| 1084 | |
| 1085 | /* Check all the user passwords for at least one to match. */ |
| 1086 | listIter li; |
| 1087 | listNode *ln; |
| 1088 | listRewind(u->passwords,&li); |
| 1089 | sds hashed = ACLHashPassword(password->ptr,sdslen(password->ptr)); |
| 1090 | while((ln = listNext(&li))) { |
| 1091 | sds thispass = listNodeValue(ln); |
| 1092 | if (!time_independent_strcmp(hashed, thispass)) { |
| 1093 | sdsfree(hashed); |
| 1094 | return C_OK; |
| 1095 | } |
| 1096 | } |
| 1097 | sdsfree(hashed); |
| 1098 | |
| 1099 | /* If we reached this point, no password matched. */ |
| 1100 | errno = EINVAL; |
| 1101 | return C_ERR; |
| 1102 | } |
| 1103 | |
| 1104 | /* This is like ACLCheckUserCredentials(), however if the user/pass |
| 1105 | * are correct, the connection is put in authenticated state and the |
no test coverage detected