Added password recovery for changing from crypt to pbkdf2 databases
This commit is contained in:
parent
a60df27bea
commit
a398b5a9a4
10
README
10
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
|
cleared out of memory as soon as unnecessary. This is done regardless of
|
||||||
which flags you compile with.
|
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
|
dgamelaunch
|
||||||
===========
|
===========
|
||||||
|
|
1
config.l
1
config.l
|
@ -118,6 +118,7 @@ chpasswd { yylval.i = DGLCMD_CHPASSWD; return TYPE_DGLCMD0; }
|
||||||
chmail { yylval.i = DGLCMD_CHMAIL; return TYPE_DGLCMD0; }
|
chmail { yylval.i = DGLCMD_CHMAIL; return TYPE_DGLCMD0; }
|
||||||
watch_menu { yylval.i = DGLCMD_WATCH_MENU; return TYPE_DGLCMD0; }
|
watch_menu { yylval.i = DGLCMD_WATCH_MENU; return TYPE_DGLCMD0; }
|
||||||
ask_login { yylval.i = DGLCMD_LOGIN; 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; }
|
ask_register { yylval.i = DGLCMD_REGISTER; return TYPE_DGLCMD0; }
|
||||||
quit { yylval.i = DGLCMD_QUIT; return TYPE_DGLCMD0; }
|
quit { yylval.i = DGLCMD_QUIT; return TYPE_DGLCMD0; }
|
||||||
play_game { yylval.i = DGLCMD_PLAYGAME; return TYPE_DGLCMD1; }
|
play_game { yylval.i = DGLCMD_PLAYGAME; return TYPE_DGLCMD1; }
|
||||||
|
|
|
@ -122,7 +122,7 @@ if test "$enable_pbkdf2" = yes; then
|
||||||
AC_DEFINE(USE_PBKDF2,1,[Enable pbkdf2 password hashing.])
|
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/rand.h], [], [AC_MSG_ERROR([openssl/rand.h not found.])], [])
|
||||||
AC_CHECK_HEADERS([openssl/evp.h], [], [AC_MSG_ERROR([openssl/evp.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
|
if test "$enable_sqlite" = no; then
|
||||||
AC_MSG_ERROR([sqlite must be enabled for pbkdf2 password hashing.])
|
AC_MSG_ERROR([sqlite must be enabled for pbkdf2 password hashing.])
|
||||||
|
|
111
dgamelaunch.c
111
dgamelaunch.c
|
@ -2032,6 +2032,7 @@ loginprompt (int from_ttyplay)
|
||||||
if (mygetnstr (pw_buf, DGL_PASSWDLEN, 0) != OK){
|
if (mygetnstr (pw_buf, DGL_PASSWDLEN, 0) != OK){
|
||||||
memset_s(pw_buf, 0, strlen(pw_buf));
|
memset_s(pw_buf, 0, strlen(pw_buf));
|
||||||
free(pw_buf);
|
free(pw_buf);
|
||||||
|
me = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2041,6 +2042,7 @@ loginprompt (int from_ttyplay)
|
||||||
free(pw_buf);
|
free(pw_buf);
|
||||||
|
|
||||||
if (me->flags & DGLACCT_LOGIN_LOCK) {
|
if (me->flags & DGLACCT_LOGIN_LOCK) {
|
||||||
|
me = NULL;
|
||||||
clear ();
|
clear ();
|
||||||
mvprintw(5, 1, "Sorry, that account has been banned.--More--");
|
mvprintw(5, 1, "Sorry, that account has been banned.--More--");
|
||||||
dgl_getch();
|
dgl_getch();
|
||||||
|
@ -3255,3 +3257,112 @@ int memset_s(void *v, int c, size_t n) {
|
||||||
|
|
||||||
return 0;
|
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
|
||||||
|
|
|
@ -81,7 +81,8 @@ typedef enum
|
||||||
DGLCMD_PLAYGAME, /* play_game "foo" */
|
DGLCMD_PLAYGAME, /* play_game "foo" */
|
||||||
DGLCMD_PLAY_IF_EXIST, /* play_if_exist "game" "file" */
|
DGLCMD_PLAY_IF_EXIST, /* play_if_exist "game" "file" */
|
||||||
DGLCMD_SUBMENU, /* submenu "foo" */
|
DGLCMD_SUBMENU, /* submenu "foo" */
|
||||||
DGLCMD_RETURN /* return */
|
DGLCMD_RETURN, /* return */
|
||||||
|
DGLCMD_UPDATEPW /* updates password for new pbkdf2 database */
|
||||||
} dglcmd_actions;
|
} dglcmd_actions;
|
||||||
|
|
||||||
typedef enum
|
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 ascii_to_byte(char *input, unsigned char* output, int keyLen);
|
||||||
extern int byte_to_ascii(unsigned char* input, 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 int memset_s(void *v, int c, size_t n);
|
||||||
|
extern void updatepw();
|
||||||
|
|
|
@ -329,6 +329,9 @@ dgl_exec_cmdqueue(struct dg_cmdpart *queue, int game, struct dg_user *me)
|
||||||
case DGLCMD_REGISTER:
|
case DGLCMD_REGISTER:
|
||||||
if (!loggedin && globalconfig.allow_registration) newuser();
|
if (!loggedin && globalconfig.allow_registration) newuser();
|
||||||
break;
|
break;
|
||||||
|
case DGLCMD_UPDATEPW:
|
||||||
|
if (!loggedin) updatepw();
|
||||||
|
break;
|
||||||
case DGLCMD_QUIT:
|
case DGLCMD_QUIT:
|
||||||
debug_write("command: quit");
|
debug_write("command: quit");
|
||||||
graceful_exit(0);
|
graceful_exit(0);
|
||||||
|
|
|
@ -141,6 +141,8 @@ default_term = "xterm"
|
||||||
# ask_login = do the login prompting, if not logged in
|
# ask_login = do the login prompting, if not logged in
|
||||||
# ask_register = do register new user prompting, if not logged in and
|
# ask_register = do register new user prompting, if not logged in and
|
||||||
# registration of new nicks is allowed.
|
# 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"
|
# play_game "foo" = start game which has the short name "foo"
|
||||||
# (user must be logged in)
|
# (user must be logged in)
|
||||||
# play_if_exist "foo" "file" = start game "foo", if file "file" exists.
|
# play_if_exist "foo" "file" = start game "foo", if file "file" exists.
|
||||||
|
|
Loading…
Reference in New Issue