diff --git a/src/kernel/faction.test.c b/src/kernel/faction.test.c index 14e3e5ac0..b249edaeb 100644 --- a/src/kernel/faction.test.c +++ b/src/kernel/faction.test.c @@ -126,8 +126,8 @@ static void test_check_passwd(CuTest *tc) { f = test_create_faction(0); faction_setpassword(f, password_hash("password")); CuAssertIntEquals(tc, true, checkpasswd(f, "password")); - CuAssertIntEquals(tc, true, checkpasswd(f, "PASSWORD")); CuAssertIntEquals(tc, false, checkpasswd(f, "assword")); + CuAssertIntEquals(tc, false, checkpasswd(f, "PASSWORD")); } static void test_get_monsters(CuTest *tc) { diff --git a/src/util/password.c b/src/util/password.c index da05480f6..e4b36fb6d 100644 --- a/src/util/password.c +++ b/src/util/password.c @@ -1,9 +1,12 @@ #include #include "password.h" +#include + #include #include #include +#include #define PASSWORD_PLAIN 0 #define PASSWORD_MD5 1 @@ -11,6 +14,8 @@ #define PASSWORD_BCRYPT 3 // not implemented #define PASSWORD_DEFAULT PASSWORD_PLAIN +#define MAXSALTLEN 32 // maximum length in characters of any salt + static const char * password_hash_i(const char * passwd, const char *salt, int algo) { static char result[64]; // TODO: static result buffers are bad mojo! assert(passwd); @@ -18,6 +23,15 @@ static const char * password_hash_i(const char * passwd, const char *salt, int a if (algo==PASSWORD_PLAIN) { _snprintf(result, sizeof(result), "$0$%s$%s", salt, passwd); } + else if (algo == PASSWORD_MD5) { + md5_state_t ms; + md5_byte_t digest[16]; + md5_init(&ms); + md5_append(&ms, (const md5_byte_t *)passwd, strlen(passwd)); + md5_append(&ms, (const md5_byte_t *)salt, strlen(salt)); + md5_finish(&ms, digest); + _snprintf(result, sizeof(result), "$1$%s$%s", salt, digest); // FIXME: need to build a hex string first! + } else { return NULL; } @@ -28,8 +42,34 @@ const char * password_hash(const char * passwd) { return password_hash_i(passwd, "saltyfish", PASSWORD_DEFAULT); } -int password_verify(const char * hash, const char * passwd) { - assert(hash); - assert(passwd); - return VERIFY_UNKNOWN; +static bool password_is_implemented(int algo) { + return algo==PASSWORD_PLAIN; +} + +int password_verify(const char * pwhash, const char * passwd) { + char salt[MAXSALTLEN+1]; + size_t len; + int algo; + char *pos; + const char *dol, *hash; + assert(pwhash); + assert(passwd); + assert(pwhash[0] == '$'); + algo = (int)strtol(pwhash + 1, &pos, 16); + assert(pos[0] == '$'); + ++pos; + dol = strchr(pos, '$'); + assert(dol>pos && dol[0] == '$'); + len = dol - pos; + assert(len <= MAXSALTLEN); + strncpy(salt, pos, len); + salt[len] = 0; + hash = password_hash_i(passwd, salt, algo); + if (!password_is_implemented(algo)) { + return VERIFY_UNKNOWN; + } + if (strcmp(pwhash, hash) == 0) { + return VERIFY_OK; + } + return VERIFY_FAIL; }