thematdev
140738e4e8
In order to use hiredis it is needed to move from ANSI C to C99 or gnu89. For now redis auth code is untested it's just first compiling prototype
132 lines
3.1 KiB
C
132 lines
3.1 KiB
C
#include "auth.h"
|
|
#include "config.h"
|
|
|
|
#include <hiredis/hiredis.h>
|
|
#include <uuid/uuid.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <tomcrypt.h>
|
|
|
|
#define UUID_SIZE 36
|
|
#define SHA512_DIGEST_SIZE 64
|
|
|
|
#define FAIL_AUTH() do { \
|
|
strcpy(session_id, ""); \
|
|
retval = 0; \
|
|
goto defer; \
|
|
} while (0)
|
|
|
|
int
|
|
user_by_session_id(const char *session_id, char *username)
|
|
{
|
|
redisContext *ctx;
|
|
redisReply *reply;
|
|
uuid_t uu_tmp;
|
|
struct timeval timeout = RA_CONNECTION_TIMEOUT;
|
|
int retval = 0;
|
|
|
|
ctx = NULL;
|
|
reply = NULL;
|
|
|
|
if (uuid_parse(session_id, uu_tmp) < 0) {
|
|
retval = -EINVAL;
|
|
goto defer;
|
|
}
|
|
|
|
ctx = redisConnectUnixWithTimeout(RA_HOSTNAME, timeout);
|
|
|
|
if (!ctx || ctx->err) {
|
|
retval = -EIO;
|
|
goto defer;
|
|
}
|
|
|
|
reply = redisCommand(ctx, "GET session:%s", session_id);
|
|
if (reply->type != REDIS_REPLY_STRING) {
|
|
strcpy(username, "");
|
|
} else {
|
|
strcpy(username, reply->str);
|
|
}
|
|
|
|
defer:
|
|
redisFree(ctx);
|
|
freeReplyObject(reply);
|
|
return retval;
|
|
}
|
|
|
|
int
|
|
authenticate(const char *username, const char *password, char *session_id)
|
|
{
|
|
redisContext *ctx;
|
|
redisReply *salt_reply, *hash_reply, *sid_reply;
|
|
char *sid;
|
|
unsigned char db_hash[SHA512_DIGEST_SIZE], got_hash[SHA512_DIGEST_SIZE];
|
|
uuid_t uu_tmp;
|
|
hash_state md;
|
|
struct timeval timeout = RA_CONNECTION_TIMEOUT;
|
|
int retval = 0;
|
|
|
|
ctx = NULL;
|
|
salt_reply = hash_reply = sid_reply = NULL;
|
|
|
|
if (strlen(username) > RA_USER_MAX_LENGTH || strlen(password) > RA_PASSWORD_MAX_LENGTH) {
|
|
retval = -EINVAL;
|
|
goto defer;
|
|
}
|
|
|
|
ctx = redisConnectUnixWithTimeout(RA_HOSTNAME, timeout);
|
|
|
|
if (!ctx || ctx->err) {
|
|
retval = -EIO;
|
|
goto defer;
|
|
}
|
|
|
|
salt_reply = redisCommand(ctx, "GET salt:%s", username);
|
|
|
|
if (salt_reply->type != REDIS_REPLY_STRING) {
|
|
FAIL_AUTH();
|
|
}
|
|
|
|
hash_reply = redisCommand(ctx, "GET hash:%s", username);
|
|
|
|
if (hash_reply->type != REDIS_REPLY_STRING || hash_reply->len != SHA512_DIGEST_SIZE) {
|
|
FAIL_AUTH();
|
|
}
|
|
|
|
memcpy(db_hash, hash_reply->str, SHA512_DIGEST_SIZE);
|
|
|
|
sha512_init(&md);
|
|
|
|
sha512_process(&md, RA_MAGIC, strlen(RA_MAGIC));
|
|
sha512_process(&md, password, strlen(password));
|
|
sha512_process(&md, salt_reply->str, strlen(salt_reply->str));
|
|
|
|
sha512_done(&md, got_hash);
|
|
|
|
if (memcmp(db_hash, got_hash, SHA512_DIGEST_SIZE)) {
|
|
FAIL_AUTH();
|
|
} else {
|
|
redisCommand(ctx, "GET session:%s", username);
|
|
if (sid_reply->type != REDIS_REPLY_STRING) {
|
|
/* assuming there is no session for this user */
|
|
freeReplyObject(sid_reply);
|
|
|
|
uuid_generate(uu_tmp);
|
|
uuid_unparse(uu_tmp, session_id);
|
|
|
|
sid_reply = redisCommand(ctx, "SET session:%s %s", username, session_id);
|
|
freeReplyObject(sid_reply);
|
|
|
|
sid_reply = redisCommand(ctx, "EXPIRY session:%s %d", username, RA_SESSION_EXPIRY);
|
|
} else {
|
|
strcpy(session_id, sid_reply->str);
|
|
}
|
|
retval = 1;
|
|
}
|
|
|
|
defer:
|
|
redisFree(ctx);
|
|
freeReplyObject(salt_reply);
|
|
freeReplyObject(hash_reply);
|
|
freeReplyObject(sid_reply);
|
|
}
|