Added password recovery for changing from crypt to pbkdf2 databases

This commit is contained in:
Phantom Voltage 2017-05-31 17:46:59 -07:00
parent a60df27bea
commit a398b5a9a4
7 changed files with 131 additions and 2 deletions

10
README
View File

@ -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
===========

View File

@ -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; }

View File

@ -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.])

View File

@ -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

View File

@ -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();

View File

@ -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);

View File

@ -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.