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. */
| 1075 | * ENONENT: if the specified user does not exist at all. |
| 1076 | */ |
| 1077 | int ACLCheckUserCredentials(robj *username, robj *password) { |
| 1078 | user *u = ACLGetUserByName(szFromObj(username),sdslen(szFromObj(username))); |
| 1079 | if (u == NULL) { |
| 1080 | errno = ENOENT; |
| 1081 | return C_ERR; |
| 1082 | } |
| 1083 | |
| 1084 | /* Disabled users can't login. */ |
| 1085 | if (u->flags & USER_FLAG_DISABLED) { |
| 1086 | errno = EINVAL; |
| 1087 | return C_ERR; |
| 1088 | } |
| 1089 | |
| 1090 | /* If the user is configured to don't require any password, we |
| 1091 | * are already fine here. */ |
| 1092 | if (u->flags & USER_FLAG_NOPASS) return C_OK; |
| 1093 | |
| 1094 | /* Check all the user passwords for at least one to match. */ |
| 1095 | listIter li; |
| 1096 | listNode *ln; |
| 1097 | listRewind(u->passwords,&li); |
| 1098 | sds hashed = ACLHashPassword((unsigned char*)szFromObj(password),sdslen(szFromObj(password))); |
| 1099 | while((ln = listNext(&li))) { |
| 1100 | sds thispass = (sds)listNodeValue(ln); |
| 1101 | if (!time_independent_strcmp(hashed, thispass)) { |
| 1102 | sdsfree(hashed); |
| 1103 | return C_OK; |
| 1104 | } |
| 1105 | } |
| 1106 | sdsfree(hashed); |
| 1107 | |
| 1108 | /* If we reached this point, no password matched. */ |
| 1109 | errno = EINVAL; |
| 1110 | return C_ERR; |
| 1111 | } |
| 1112 | |
| 1113 | /* This is like ACLCheckUserCredentials(), however if the user/pass |
| 1114 | * are correct, the connection is put in authenticated state and the |
no test coverage detected