From 1d5856cfe64e778c70fece0d08d36f153be16600 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 14 Jul 2006 13:05:48 +0200 Subject: two-stage password reset This patch changes the password reset function to a two-stage process. After requesting a new password a confirmation email is sent first, only if the link contained in this mail is used the password is changed for real. This makes sure malicious people can't reset passwords for other users. darcs-hash:20060714110548-7ad00-c1e23fd51cc2d2f16473914421ebe0f9c3b2ba8c.gz --- inc/auth.php | 101 +++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 78 insertions(+), 23 deletions(-) (limited to 'inc/auth.php') diff --git a/inc/auth.php b/inc/auth.php index 345a2ba67..467f4b0cd 100644 --- a/inc/auth.php +++ b/inc/auth.php @@ -570,8 +570,14 @@ function updateprofile() { /** * Send a new password * + * This function handles both phases of the password reset: + * + * - handling the first request of password reset + * - validating the password reset auth token + * * @author Benoit Chesneau * @author Chris Smith + * @author Andreas Gohr * * @return bool true on success, false on any error */ @@ -580,40 +586,89 @@ function act_resendpwd(){ global $conf; global $auth; - if(!$_POST['save']) return false; if(!actionOK('resendpwd')) return false; // should not be able to get here without modPass being possible... if(!$auth->canDo('modPass')) { - msg($lang['resendna'],-1); - return false; + msg($lang['resendna'],-1); + return false; } - if (empty($_POST['login'])) { - msg($lang['resendpwdmissing'], -1); - return false; - } else { - $user = $_POST['login']; - } + $token = preg_replace('/[^a-f0-9]+/','',$_REQUEST['pwauth']); - $userinfo = $auth->getUserData($user); - if(!$userinfo['mail']) { - msg($lang['resendpwdnouser'], -1); - return false; - } + if($token){ + // we're in token phase - $pass = auth_pwgen(); - if (!$auth->modifyUser($user,array('pass' => $pass))) { - msg('error modifying user data',-1); - return false; - } + $tfile = $conf['cachedir'].'/'.$token{0}.'/'.$token.'.pwauth'; + if(!@file_exists($tfile)){ + msg($lang['resendpwdbadauth'],-1); + return false; + } + $user = io_readfile($tfile); + @unlink($tfile); + $userinfo = $auth->getUserData($user); + if(!$userinfo['mail']) { + msg($lang['resendpwdnouser'], -1); + return false; + } + + $pass = auth_pwgen(); + if (!$auth->modifyUser($user,array('pass' => $pass))) { + msg('error modifying user data',-1); + return false; + } + + if (auth_sendPassword($user,$pass)) { + msg($lang['resendpwdsuccess'],1); + } else { + msg($lang['regmailfail'],-1); + } + return true; - if (auth_sendPassword($user,$pass)) { - msg($lang['resendpwdsuccess'],1); } else { - msg($lang['regmailfail'],-1); + // we're in request phase + + if(!$_POST['save']) return false; + + if (empty($_POST['login'])) { + msg($lang['resendpwdmissing'], -1); + return false; + } else { + $user = $_POST['login']; + } + + $userinfo = $auth->getUserData($user); + if(!$userinfo['mail']) { + msg($lang['resendpwdnouser'], -1); + return false; + } + + // generate auth token + $token = md5(auth_cookiesalt().$user); //secret but user based + $tfile = $conf['cachedir'].'/'.$token{0}.'/'.$token.'.pwauth'; + $url = wl('',array('do'=>'resendpwd','pwauth'=>$token),true,'&'); + + io_saveFile($tfile,$user); + + $text = rawLocale('pwconfirm'); + $text = str_replace('@DOKUWIKIURL@',DOKU_URL,$text); + $text = str_replace('@FULLNAME@',$userinfo['name'],$text); + $text = str_replace('@LOGIN@',$user,$text); + $text = str_replace('@TITLE@',$conf['title'],$text); + $text = str_replace('@CONFIRM@',$url,$text); + + if(mail_send($userinfo['name'].' <'.$userinfo['mail'].'>', + $lang['regpwmail'], + $text, + $conf['mailfrom'])){ + msg($lang['resendpwdconfirm'],1); + }else{ + msg($lang['regmailfail'],-1); + } + return true; } - return true; + + return false; // never reached } /** -- cgit v1.2.3