mirror of
https://github.com/fluencelabs/redis
synced 2025-04-09 10:46:06 +00:00
96 lines
4.1 KiB
C
96 lines
4.1 KiB
C
|
/*
|
||
|
* Copyright (c) 2018, Salvatore Sanfilippo <antirez at gmail dot com>
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions are met:
|
||
|
*
|
||
|
* * Redistributions of source code must retain the above copyright notice,
|
||
|
* this list of conditions and the following disclaimer.
|
||
|
* * Redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer in the
|
||
|
* documentation and/or other materials provided with the distribution.
|
||
|
* * Neither the name of Redis nor the names of its contributors may be used
|
||
|
* to endorse or promote products derived from this software without
|
||
|
* specific prior written permission.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||
|
*/
|
||
|
|
||
|
#include "server.h"
|
||
|
|
||
|
/* Return zero if strings are the same, non-zero if they are not.
|
||
|
* The comparison is performed in a way that prevents an attacker to obtain
|
||
|
* information about the nature of the strings just monitoring the execution
|
||
|
* time of the function.
|
||
|
*
|
||
|
* Note that limiting the comparison length to strings up to 512 bytes we
|
||
|
* can avoid leaking any information about the password length and any
|
||
|
* possible branch misprediction related leak.
|
||
|
*/
|
||
|
int time_independent_strcmp(char *a, char *b) {
|
||
|
char bufa[CONFIG_AUTHPASS_MAX_LEN], bufb[CONFIG_AUTHPASS_MAX_LEN];
|
||
|
/* The above two strlen perform len(a) + len(b) operations where either
|
||
|
* a or b are fixed (our password) length, and the difference is only
|
||
|
* relative to the length of the user provided string, so no information
|
||
|
* leak is possible in the following two lines of code. */
|
||
|
unsigned int alen = strlen(a);
|
||
|
unsigned int blen = strlen(b);
|
||
|
unsigned int j;
|
||
|
int diff = 0;
|
||
|
|
||
|
/* We can't compare strings longer than our static buffers.
|
||
|
* Note that this will never pass the first test in practical circumstances
|
||
|
* so there is no info leak. */
|
||
|
if (alen > sizeof(bufa) || blen > sizeof(bufb)) return 1;
|
||
|
|
||
|
memset(bufa,0,sizeof(bufa)); /* Constant time. */
|
||
|
memset(bufb,0,sizeof(bufb)); /* Constant time. */
|
||
|
/* Again the time of the following two copies is proportional to
|
||
|
* len(a) + len(b) so no info is leaked. */
|
||
|
memcpy(bufa,a,alen);
|
||
|
memcpy(bufb,b,blen);
|
||
|
|
||
|
/* Always compare all the chars in the two buffers without
|
||
|
* conditional expressions. */
|
||
|
for (j = 0; j < sizeof(bufa); j++) {
|
||
|
diff |= (bufa[j] ^ bufb[j]);
|
||
|
}
|
||
|
/* Length must be equal as well. */
|
||
|
diff |= alen ^ blen;
|
||
|
return diff; /* If zero strings are the same. */
|
||
|
}
|
||
|
|
||
|
/* 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.
|
||
|
*/
|
||
|
int ACLCheckUserCredentials(robj *username, robj *password) {
|
||
|
/* For now only the "default" user is allowed. When the RCP1 ACLs
|
||
|
* will be implemented multiple usernames will be supproted. */
|
||
|
if (username != NULL && strcmp(username->ptr,"default")) {
|
||
|
errno = ENOENT;
|
||
|
return C_ERR;
|
||
|
}
|
||
|
|
||
|
/* For now we just compare the password with the system wide one. */
|
||
|
if (!time_independent_strcmp(password->ptr, server.requirepass)) {
|
||
|
return C_OK;
|
||
|
} else {
|
||
|
errno = EINVAL;
|
||
|
return C_ERR;
|
||
|
}
|
||
|
}
|