From a398b5a9a476aac7b7b4ee618761adff5e1f3ed8 Mon Sep 17 00:00:00 2001 From: Phantom Voltage Date: Wed, 31 May 2017 17:46:59 -0700 Subject: [PATCH] Added password recovery for changing from crypt to pbkdf2 databases --- README | 10 ++++ config.l | 1 + configure.ac | 2 +- dgamelaunch.c | 111 ++++++++++++++++++++++++++++++++++++++ dgamelaunch.h | 4 +- dgl-common.c | 3 ++ examples/dgamelaunch.conf | 2 + 7 files changed, 131 insertions(+), 2 deletions(-) diff --git a/README b/README index afa0fe5..623a231 100644 --- a/README +++ b/README @@ -17,6 +17,16 @@ In addition, strings that ever hold raw passwords from the user, are now cleared out of memory as soon as unnecessary. This is done regardless of which flags you compile with. +If you have an sqlite3 database using the old password hashing method, +there's a new command you can include in dgamelaunch.conf to transfer +users over to the new database. + +update_passwd will prompt users to login, if they successfully +login using their old password, it will prompt them to change +their password. The resulting password will be salted and hashed +with pbkdf2. For this to work, you must merge the old database +with the new one, with the salt entry as an empty string for users +who still need to migrate their passwords over. dgamelaunch =========== diff --git a/config.l b/config.l index b3b78d4..3412b87 100644 --- a/config.l +++ b/config.l @@ -118,6 +118,7 @@ chpasswd { yylval.i = DGLCMD_CHPASSWD; return TYPE_DGLCMD0; } chmail { yylval.i = DGLCMD_CHMAIL; return TYPE_DGLCMD0; } watch_menu { yylval.i = DGLCMD_WATCH_MENU; return TYPE_DGLCMD0; } ask_login { yylval.i = DGLCMD_LOGIN; return TYPE_DGLCMD0; } +update_passwd { yylval.i = DGLCMD_UPDATEPW; return TYPE_DGLCMD0; } ask_register { yylval.i = DGLCMD_REGISTER; return TYPE_DGLCMD0; } quit { yylval.i = DGLCMD_QUIT; return TYPE_DGLCMD0; } play_game { yylval.i = DGLCMD_PLAYGAME; return TYPE_DGLCMD1; } diff --git a/configure.ac b/configure.ac index a3c455f..1efa00a 100644 --- a/configure.ac +++ b/configure.ac @@ -122,7 +122,7 @@ if test "$enable_pbkdf2" = yes; then AC_DEFINE(USE_PBKDF2,1,[Enable pbkdf2 password hashing.]) AC_CHECK_HEADERS([openssl/rand.h], [], [AC_MSG_ERROR([openssl/rand.h not found.])], []) AC_CHECK_HEADERS([openssl/evp.h], [], [AC_MSG_ERROR([openssl/evp.h not found.])], []) - MY_LIBS="$MY_LIBS -lcrypto" + MY_LIBS="$MY_LIBS -lcrypto -lcrypt" if test "$enable_sqlite" = no; then AC_MSG_ERROR([sqlite must be enabled for pbkdf2 password hashing.]) diff --git a/dgamelaunch.c b/dgamelaunch.c index d246d85..4d7596f 100644 --- a/dgamelaunch.c +++ b/dgamelaunch.c @@ -2032,6 +2032,7 @@ loginprompt (int from_ttyplay) if (mygetnstr (pw_buf, DGL_PASSWDLEN, 0) != OK){ memset_s(pw_buf, 0, strlen(pw_buf)); free(pw_buf); + me = NULL; return; } @@ -2041,6 +2042,7 @@ loginprompt (int from_ttyplay) free(pw_buf); if (me->flags & DGLACCT_LOGIN_LOCK) { + me = NULL; clear (); mvprintw(5, 1, "Sorry, that account has been banned.--More--"); dgl_getch(); @@ -3255,3 +3257,112 @@ int memset_s(void *v, int c, size_t n) { return 0; } + +/* if me, free */ +/* get username, check ifalnum */ + +/* check if username has salt */ + +/* if has salt, ignore, but go through following steps */ + +/* get oldpw, check w/ crypt */ + +/* if error w/ passwords or salt, exit */ + + +#ifdef USE_PBKDF2 +void updatepw() +{ + + char user_buf[DGL_PLAYERNAMELEN+1]; + char* pw_buf; + char *crypted; + + int error = 2; + + loggedin = 0; + + while (error) + { + clear (); + + drawbanner (&banner); + + mvaddstr (5, 1, + "Please enter your username. (blank entry aborts)"); + mvaddstr (7, 1, "=> "); + + if (error == 1) + { + mvaddstr (9, 1, "There was a problem with your last entry."); + move (7, 4); + } + + refresh (); + + if (mygetnstr (user_buf, DGL_PLAYERNAMELEN, 1) != OK) + return; + + if (*user_buf == '\0') + return; + + error = 1; + + { + struct dg_user *tmpme; + if ((tmpme = userexist(user_buf, 0))) { + me = cpy_me(tmpme); + error = 0; + } + } + } + + clear (); + + drawbanner (&banner); + + pw_buf = (char*)malloc((DGL_PASSWDLEN+2)* sizeof(char)); + + mvaddstr (5, 1, "Please enter your password."); + mvaddstr (7, 1, "=> "); + + refresh (); + + if (mygetnstr (pw_buf, DGL_PASSWDLEN, 0) != OK){ + memset_s(pw_buf, 0, strlen(pw_buf)); + free(pw_buf); + return; + } + + crypted = crypt (pw_buf, pw_buf); + memset_s(pw_buf, 0, strlen(pw_buf)); + free(pw_buf); + + if (strlen(me->salt) || crypted==NULL || strncmp(crypted, me->password, DGL_PASSWDLEN)){ + + clear (); + drawbanner (&banner); + mvaddstr (5, 1, "There was a problem updating your password."); + mvaddstr (6, 1, "Either old password is incorrect or password already updated."); + refresh (); + dgl_getch(); + return; + } + + + if (me->flags & DGLACCT_LOGIN_LOCK) { + clear (); + mvprintw(5, 1, "Sorry, that account has been banned.--More--"); + refresh (); + dgl_getch(); + return; + } + + + changepw(1); + loggedin = 1; + setproctitle("%s", me->username); + dgl_exec_cmdqueue(globalconfig.cmdqueue[DGLTIME_LOGIN], 0, me); + return; +} +#endif diff --git a/dgamelaunch.h b/dgamelaunch.h index 46e5843..435d3c3 100644 --- a/dgamelaunch.h +++ b/dgamelaunch.h @@ -81,7 +81,8 @@ typedef enum DGLCMD_PLAYGAME, /* play_game "foo" */ DGLCMD_PLAY_IF_EXIST, /* play_if_exist "game" "file" */ DGLCMD_SUBMENU, /* submenu "foo" */ - DGLCMD_RETURN /* return */ + DGLCMD_RETURN, /* return */ + DGLCMD_UPDATEPW /* updates password for new pbkdf2 database */ } dglcmd_actions; typedef enum @@ -379,3 +380,4 @@ extern int mygetnstr(char *buf, int maxlen, int doecho); extern int ascii_to_byte(char *input, unsigned char* output, int keyLen); extern int byte_to_ascii(unsigned char* input, char* output, int keyLen); extern int memset_s(void *v, int c, size_t n); +extern void updatepw(); diff --git a/dgl-common.c b/dgl-common.c index 80560b5..0b5683d 100644 --- a/dgl-common.c +++ b/dgl-common.c @@ -329,6 +329,9 @@ dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me) case DGLCMD_REGISTER: if (!loggedin && globalconfig.allow_registration) newuser(); break; + case DGLCMD_UPDATEPW: + if (!loggedin) updatepw(); + break; case DGLCMD_QUIT: debug_write("command: quit"); graceful_exit(0); diff --git a/examples/dgamelaunch.conf b/examples/dgamelaunch.conf index 2a79175..0679289 100644 --- a/examples/dgamelaunch.conf +++ b/examples/dgamelaunch.conf @@ -141,6 +141,8 @@ default_term = "xterm" # ask_login = do the login prompting, if not logged in # ask_register = do register new user prompting, if not logged in and # registration of new nicks is allowed. +# update_passwd = prompts user for old password to create new +# password using pbkdf2 hashing # play_game "foo" = start game which has the short name "foo" # (user must be logged in) # play_if_exist "foo" "file" = start game "foo", if file "file" exists.