add a new password module

start adding password hashing logic (WIP)
does not yet pass all tests
This commit is contained in:
Enno Rehling 2016-01-12 23:52:30 +01:00
parent ae0206652e
commit 54d25e91dd
11 changed files with 100 additions and 20 deletions

View File

@ -31,6 +31,8 @@ without prior permission by the authors of Eressea.
#include <util/language.h>
#include <util/log.h>
#include <util/password.h>
#include <quicklist.h>
#include <tolua.h>
@ -383,7 +385,8 @@ static int tolua_faction_create(lua_State * L)
static int tolua_faction_set_password(lua_State * L)
{
faction *self = (faction *)tolua_tousertype(L, 1, 0);
faction_setpassword(self, tolua_tostring(L, 2, 0));
const char * passw = tolua_tostring(L, 2, 0);
faction_setpassword(self, password_hash(passw));
return 0;
}

View File

@ -19,7 +19,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <platform.h>
#include <kernel/config.h>
#include "faction.h"
#include "alliance.h"
#include "ally.h"
#include "curse.h"
@ -46,6 +45,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/language.h>
#include <util/log.h>
#include <util/parser.h>
#include <util/password.h>
#include <util/resolve.h>
#include <util/rng.h>
#include <util/variant.h>
@ -63,6 +63,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
faction *factions;
@ -252,7 +253,7 @@ faction *addfaction(const char *email, const char *password,
}
if (!password) password = itoa36(rng_int());
faction_setpassword(f, password);
faction_setpassword(f, password_hash(password));
ADDMSG(&f->msgs, msg_message("changepasswd", "value", password));
f->alliance_joindate = turn;
@ -313,16 +314,27 @@ unit *addplayer(region * r, faction * f)
return u;
}
extern char *sha256_crypt(const char *key, const char *salt);
const char * mksalt(char *salt, size_t len) {
char *dst = salt;
int ent = (int)time(0);
// FIXME: worst ever salt generation
while (dst < salt + len) {
*dst++ = itoa36(ent & rng_int())[0];
}
return salt;
}
bool checkpasswd(const faction * f, const char *passwd)
{
if (!passwd) return false;
if (strcmp(f->_password, passwd)==0) return true;
if (unicode_utf8_strcasecmp(f->_password, passwd) == 0) {
log_warning("case-sensitive password check failed: %s", factionname(f));
return true;
if (password_verify(f->_password, passwd) == VERIFY_FAIL) {
log_warning("password check failed: %s", factionname(f));
return false;
}
log_warning("password check failed: %s", factionname(f));
return false;
return true;
}
variant read_faction_reference(struct storage * store)
@ -565,11 +577,11 @@ void faction_setbanner(faction * self, const char *banner)
self->banner = _strdup(banner);
}
void faction_setpassword(faction * f, const char *passw)
void faction_setpassword(faction * f, const char *pwhash)
{
assert(passw);
assert(pwhash && pwhash[0] == '$');
free(f->_password);
f->_password = _strdup(passw);
f->_password = _strdup(pwhash);
}
bool valid_race(const struct faction *f, const struct race *rc)

View File

@ -153,8 +153,7 @@ extern "C" {
const char *faction_getemail(const struct faction *self);
void faction_setemail(struct faction *self, const char *email);
// const char *faction_getpassword(const struct faction *self);
void faction_setpassword(struct faction *self, const char *password);
void faction_setpassword(struct faction *self, const char *pwhash);
bool valid_race(const struct faction *f, const struct race *rc);
void faction_getorigin(const struct faction * f, int id, int *x, int *y);

View File

@ -8,6 +8,7 @@
#include <kernel/plane.h>
#include <kernel/config.h>
#include <util/language.h>
#include <util/password.h>
#include "monster.h"
#include <CuTest.h>
@ -123,7 +124,7 @@ static void test_check_passwd(CuTest *tc) {
faction *f;
f = test_create_faction(0);
faction_setpassword(f, "password");
faction_setpassword(f, password_hash("password"));
CuAssertIntEquals(tc, true, checkpasswd(f, "password"));
CuAssertIntEquals(tc, true, checkpasswd(f, "PASSWORD"));
CuAssertIntEquals(tc, false, checkpasswd(f, "assword"));

View File

@ -64,13 +64,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/lists.h>
#include <util/log.h>
#include <util/parser.h>
#include <quicklist.h>
#include <util/password.h>
#include <util/rand.h>
#include <util/resolve.h>
#include <util/rng.h>
#include <util/umlaut.h>
#include <util/unicode.h>
#include <quicklist.h>
#include <stream.h>
#include <filestream.h>
#include <storage.h>
@ -1216,7 +1217,7 @@ faction *readfaction(struct gamedata * data)
}
READ_STR(data->store, name, sizeof(name));
faction_setpassword(f, name);
faction_setpassword(f, (data->version >= CRYPT_VERSION) ? name : password_hash(name));
if (data->version < NOOVERRIDE_VERSION) {
READ_STR(data->store, 0, 0);
}

View File

@ -33,8 +33,8 @@
#define SPELL_LEVEL_VERSION 348 /* f->max_spelllevel gets stored, not calculated */
#define OWNER_3_VERSION 349 /* regions store last owner, not last alliance */
#define ATTRIBOWNER_VERSION 350 /* all attrib_type functions know who owns the attribute */
#define RELEASE_VERSION ATTRIBOWNER_VERSION /* current datafile */
#define CRYPT_VERSION 351 /* passwords are encrypted */
#define RELEASE_VERSION CRYPT_VERSION /* current datafile */
#define MIN_VERSION INTPAK_VERSION /* minimal datafile we support */
#define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */

View File

@ -79,6 +79,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/lists.h>
#include <util/log.h>
#include <util/parser.h>
#include <util/password.h>
#include <quicklist.h>
#include <util/rand.h>
#include <util/rng.h>
@ -2169,7 +2170,7 @@ int password_cmd(unit * u, struct order *ord)
cmistake(u, ord, 283, MSG_EVENT);
strlcpy(pwbuf, itoa36(rng_int()), sizeof(pwbuf));
}
faction_setpassword(u->faction, pwbuf);
faction_setpassword(u->faction, password_hash(pwbuf));
ADDMSG(&u->faction->msgs, msg_message("changepasswd",
"value", pwbuf));
return 0;

View File

@ -3,6 +3,7 @@ project(util C)
SET(_TEST_FILES
base36.test.c
parser.test.c
password.test.c
attrib.test.c
strings.test.c
bsdstring.test.c
@ -28,6 +29,7 @@ log.c
message.c
nrmessage.c
parser.c
password.c
rand.c
resolve.c
strings.c

35
src/util/password.c Normal file
View File

@ -0,0 +1,35 @@
#include <platform.h>
#include "password.h"
#include <assert.h>
#include <string.h>
#include <stdio.h>
#define PASSWORD_PLAIN 0
#define PASSWORD_MD5 1
#define PASSWORD_SHA256 2
#define PASSWORD_BCRYPT 3 // not implemented
#define PASSWORD_DEFAULT PASSWORD_PLAIN
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);
assert(salt);
if (algo==PASSWORD_PLAIN) {
_snprintf(result, sizeof(result), "$0$%s$%s", salt, passwd);
}
else {
return NULL;
}
return result;
}
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;
}

7
src/util/password.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#define VERIFY_OK 0 // password matches hash
#define VERIFY_FAIL 1 // password is wrong
#define VERIFY_UNKNOWN 2 // hashing algorithm not supported
int password_verify(const char * hash, const char * passwd);
const char * password_hash(const char * passwd);

19
src/util/password.test.c Normal file
View File

@ -0,0 +1,19 @@
#include <CuTest.h>
#include "password.h"
static void test_passwords(CuTest *tc) {
const char *hash;
hash = password_hash("password");
CuAssertPtrNotNull(tc, hash);
CuAssertStrEquals(tc, "$0$saltyfish$password", hash);
CuAssertIntEquals(tc, VERIFY_OK, password_verify(hash, "password"));
CuAssertIntEquals(tc, VERIFY_FAIL, password_verify(hash, "arseword"));
CuAssertIntEquals(tc, VERIFY_UNKNOWN, password_verify("$9$saltyfish$password", "arseword"));
}
CuSuite *get_password_suite(void) {
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_passwords);
return suite;
}