function doTxpValidate() { global $logout, $txpcfg; $p_userid = ps('p_userid'); $p_password = ps('p_password'); $logout = gps('logout'); $stay = ps('stay'); if ($logout) { setcookie('txp_login', '', time() - 3600); } if (!empty($_COOKIE['txp_login']) and !$logout) { // cookie exists @(list($c_userid, $cookie_hash) = split(',', $_COOKIE['txp_login'])); $nonce = safe_field('nonce', 'txp_users', "name='{$c_userid}'"); if (md5($c_userid . $nonce) === $cookie_hash && $nonce) { // check nonce $GLOBALS['txp_user'] = $c_userid; // cookie is good, create $txp_user return ''; } else { // something's gone wrong $GLOBALS['txp_user'] = ''; setcookie('txp_login', '', time() - 3600); return gTxt('bad_cookie'); } } elseif ($p_userid and $p_password) { // no cookie, but incoming login vars sleep(3); // should grind dictionary attacks to a halt if (txp_validate($p_userid, $p_password)) { $nonce = safe_field('nonce', 'txp_users', "name='{$p_userid}'"); if (!$nonce) { define('TXP_UPDATE', 1); include_once txpath . '/update/_update.php'; exit(graf('Please reload')); } if ($stay) { // persistent cookie required setcookie('txp_login', $p_userid . ',' . md5($p_userid . $nonce), time() + 3600 * 24 * 365); // expires in 1 year } else { // session-only cookie required setcookie('txp_login', $p_userid . ',' . md5($p_userid . $nonce)); setcookie('txp_nostay', '1', time() + 3600 * 24 * 365); // remember nostay for 1 year } $GLOBALS['txp_user'] = $p_userid; // login is good, create $txp_user return ''; } else { $GLOBALS['txp_user'] = ''; return gTxt('could_not_log_in'); } } else { $GLOBALS['txp_user'] = ''; return gTxt('login_to_textpattern'); } }
function doTxpValidate() { global $logout, $txpcfg; $p_userid = ps('p_userid'); $p_password = ps('p_password'); $logout = gps('logout'); $stay = ps('stay'); if ($logout) { setcookie('txp_login', ' ', time() - 3600); } if (isset($_COOKIE['txp_login']) and !$logout) { // cookie exists list($c_userid, $cookie_hash) = split(',', $_COOKIE['txp_login']); $nonce = safe_field('nonce', 'txp_users', "name='{$c_userid}'"); if (md5($c_userid . $nonce) == $cookie_hash) { // check secret word $GLOBALS['txp_user'] = $c_userid; // cookie is good, create $txp_user return ''; } else { // something's gone wrong $GLOBALS['txp_user'] = ''; setcookie('txp_login', '', time() - 3600); return gTxt('bad_cookie'); } } elseif ($p_userid and $p_password) { // no cookie, but incoming login vars sleep(3); // should grind dictionary attacks to a halt if (txp_validate($p_userid, $p_password)) { $nonce = safe_field('nonce', 'txp_users', "name='{$p_userid}'"); if (!$nonce) { exit(graf('Missing authentication information. Please run _update.php')); } if ($stay) { // persistent cookie required setcookie('txp_login', $p_userid . ',' . md5($p_userid . $nonce), time() + 3600 * 24 * 365); // expires in 1 year } else { // session-only cookie required setcookie('txp_login', $p_userid . ',' . md5($p_userid . $nonce)); } $GLOBALS['txp_user'] = $p_userid; // login is good, create $txp_user return ''; } else { $GLOBALS['txp_user'] = ''; return gTxt('could_not_log_in'); } } else { $GLOBALS['txp_user'] = ''; return gTxt('login_to_textpattern'); } }
function doTxpValidate() { global $logout, $txpcfg, $txp_user; $p_userid = ps('p_userid'); $p_password = ps('p_password'); $logout = gps('logout'); $stay = ps('stay'); if ($logout) { setcookie('txp_login', '', time() - 3600); } if (!empty($_COOKIE['txp_login']) and !$logout) { @(list($c_userid, $cookie_hash) = split(',', cs('txp_login'))); $nonce = safe_field('nonce', 'txp_users', "name='" . doSlash($c_userid) . "'"); if ($nonce && $nonce === md5($c_userid . pack('H*', $cookie_hash))) { // cookie is good, create $txp_user $txp_user = $c_userid; return ''; } else { // something's gone wrong $txp_user = ''; setcookie('txp_login', '', time() - 3600); return gTxt('bad_cookie'); } } elseif ($p_userid and $p_password) { sleep(3); // should grind dictionary attacks to a halt if (txp_validate($p_userid, $p_password)) { $cookie_hash = md5(uniqid(rand())); safe_update('txp_users', "nonce = '" . doSlash(md5($p_userid . pack('H*', $cookie_hash))) . "'", "name = '" . doSlash($p_userid) . "'"); if ($stay) { setcookie('txp_login', $p_userid . ',' . $cookie_hash, time() + 3600 * 24 * 365); // expires in 1 year if (cs('txp_nostay')) { setcookie('txp_nostay', '', time() - 3600); } } else { setcookie('txp_login', $p_userid . ',' . $cookie_hash); setcookie('txp_nostay', '1', time() + 3600 * 24 * 365); // remember nostay for 1 year } $txp_user = $p_userid; // login is good, create $txp_user return ''; } else { $txp_user = ''; return gTxt('could_not_log_in'); } } else { $txp_user = ''; return gTxt('login_to_textpattern'); } }
/** * Attemp to validates the user with the provided password * or takes it from the global scope, assuming the user is logged in * @param string $user login name of the user to validate * @param string(optional) $password for that user * @access private * @return boolean, true if user is logged in */ function _validate($user, $password = NULL) { if ($password !== NULL) { $r = txp_validate($user, $password); } else { $r = true; } if ($r) { // update the last access time $safe_user = addslashes($user); safe_update("txp_users", "last_access = now()", "name = '{$safe_user}'"); return true; } return false; }
/** * Validates the given user credentials. * * @param string $user The username * @param string $password The password * @return bool TRUE on success * @access private */ public function _validate($user, $password = null) { if ($password !== null) { $r = txp_validate($user, $password); } else { $r = true; } if ($r) { // Update the last access time. $safe_user = addslashes($user); safe_update('txp_users', "last_access = NOW()", "name = '{$safe_user}'"); return true; } return false; }
function doTxpValidate() { global $logout, $txp_user; $p_userid = ps('p_userid'); $p_password = ps('p_password'); $p_reset = ps('p_reset'); $stay = ps('stay'); $logout = gps('logout'); $message = ''; $pub_path = preg_replace('|//$|', '/', rhu . '/'); if (cs('txp_login') and strpos(cs('txp_login'), ',')) { $txp_login = explode(',', cs('txp_login')); $c_hash = end($txp_login); $c_userid = join(',', array_slice($txp_login, 0, -1)); } else { $c_hash = ''; $c_userid = ''; } if ($logout) { setcookie('txp_login', '', time() - 3600); setcookie('txp_login_public', '', time() - 3600, $pub_path); } if ($c_userid and strlen($c_hash) == 32) { $nonce = safe_field('nonce', 'txp_users', "name='" . doSlash($c_userid) . "' AND last_access > DATE_SUB(NOW(), INTERVAL 30 DAY)"); if ($nonce and $nonce === md5($c_userid . pack('H*', $c_hash))) { // cookie is good if ($logout) { // destroy nonce safe_update('txp_users', "nonce = '" . doSlash(md5(uniqid(mt_rand(), TRUE))) . "'", "name = '" . doSlash($c_userid) . "'"); } else { // create $txp_user $txp_user = $c_userid; } return $message; } else { setcookie('txp_login', $c_userid, time() + 3600 * 24 * 365); setcookie('txp_login_public', '', time() - 3600, $pub_path); $message = array(gTxt('bad_cookie'), E_ERROR); } } elseif ($p_userid and $p_password) { $name = txp_validate($p_userid, $p_password); if ($name !== FALSE) { $c_hash = md5(uniqid(mt_rand(), TRUE)); $nonce = md5($name . pack('H*', $c_hash)); safe_update('txp_users', "nonce = '" . doSlash($nonce) . "'", "name = '" . doSlash($name) . "'"); setcookie('txp_login', $name . ',' . $c_hash, $stay ? time() + 3600 * 24 * 365 : 0, null, null, null, LOGIN_COOKIE_HTTP_ONLY); setcookie('txp_login_public', substr(md5($nonce), -10) . $name, $stay ? time() + 3600 * 24 * 30 : 0, $pub_path); // login is good, create $txp_user $txp_user = $name; return ''; } else { sleep(3); $message = array(gTxt('could_not_log_in'), E_ERROR); } } elseif ($p_reset) { sleep(3); include_once txpath . '/lib/txplib_admin.php'; $message = $p_userid ? send_reset_confirmation_request($p_userid) : ''; } elseif (gps('reset')) { $message = ''; } elseif (gps('confirm')) { sleep(3); $confirm = pack('H*', gps('confirm')); $name = substr($confirm, 5); $nonce = safe_field('nonce', 'txp_users', "name = '" . doSlash($name) . "'"); if ($nonce and $confirm === pack('H*', substr(md5($nonce), 0, 10)) . $name) { include_once txpath . '/lib/txplib_admin.php'; $message = reset_author_pass($name); } } $txp_user = ''; return $message; }
/** * Changes current user's password. */ function change_pass() { global $txp_user; extract(psa(array('current_pass', 'new_pass'))); if (empty($new_pass)) { new_pass_form(array(gTxt('password_required'), E_ERROR)); return; } if (txp_validate($txp_user, $current_pass)) { $rs = change_user_password($txp_user, $new_pass); if ($rs) { $message = gTxt('password_changed'); author_list($message); } } else { new_pass_form(array(gTxt('password_invalid'), E_ERROR)); } }
/** * Validates the sent login form and creates a session. * * During the reset request procedure, it is conceivable to verify the * token as soon as it's presented in the URL, but that would: * a) require refactoring code similarities in both p_confirm and p_alter branches * b) require some way (e.g. an Exception) to signal back to doLoginForm() that * the token is bogus so the 'change your password' form is not displayed. * c) leak information about the validity of a token, thus allowing rapid brute-force * attempts. * * The inconvenience of a real user following an expired token and being told so * after they've set a password is a small price to pay for the improved security * and reduction of attack surface that validating after submission affords. * * @todo Could the checks be done via a (reusable) Validator()? * * @return string A localised feedback message * @see doLoginForm() */ function doTxpValidate() { global $logout, $txp_user; $p_userid = ps('p_userid'); $p_password = ps('p_password'); $p_reset = ps('p_reset'); $p_alter = ps('p_alter'); $p_set = ps('p_set'); $stay = ps('stay'); $p_confirm = gps('confirm'); $logout = gps('logout'); $message = ''; $pub_path = preg_replace('|//$|', '/', rhu . '/'); if (cs('txp_login') && strpos(cs('txp_login'), ',')) { $txp_login = explode(',', cs('txp_login')); $c_hash = end($txp_login); $c_userid = join(',', array_slice($txp_login, 0, -1)); } else { $c_hash = ''; $c_userid = ''; } if ($logout) { setcookie('txp_login', '', time() - 3600); setcookie('txp_login_public', '', time() - 3600, $pub_path); } if ($c_userid && strlen($c_hash) === 32) { // Cookie exists. // @todo Improve security by using a better nonce/salt mechanism. md5 and uniqid are bad. $r = safe_row("name, nonce", 'txp_users', "name = '" . doSlash($c_userid) . "' AND last_access > DATE_SUB(NOW(), INTERVAL 30 DAY)"); if ($r && $r['nonce'] && $r['nonce'] === md5($c_userid . pack('H*', $c_hash))) { // Cookie is good. if ($logout) { // Destroy nonce. safe_update('txp_users', "nonce = '" . doSlash(md5(uniqid(mt_rand(), true))) . "'", "name = '" . doSlash($c_userid) . "'"); } else { // Create $txp_user. $txp_user = $r['name']; } return $message; } else { txp_status_header('401 Your session has expired'); setcookie('txp_login', $c_userid, time() + 3600 * 24 * 365); setcookie('txp_login_public', '', time() - 3600, $pub_path); $message = array(gTxt('bad_cookie'), E_ERROR); } } elseif ($p_userid && $p_password) { // Incoming login vars. $name = txp_validate($p_userid, $p_password); if ($name !== false) { $c_hash = md5(uniqid(mt_rand(), true)); $nonce = md5($name . pack('H*', $c_hash)); safe_update('txp_users', "nonce = '" . doSlash($nonce) . "'", "name = '" . doSlash($name) . "'"); setcookie('txp_login', $name . ',' . $c_hash, $stay ? time() + 3600 * 24 * 365 : 0, null, null, null, LOGIN_COOKIE_HTTP_ONLY); setcookie('txp_login_public', substr(md5($nonce), -10) . $name, $stay ? time() + 3600 * 24 * 30 : 0, $pub_path); // Login is good, create $txp_user. $txp_user = $name; return ''; } else { sleep(3); txp_status_header('401 Could not log in with that username/password'); $message = array(gTxt('could_not_log_in'), E_ERROR); } } elseif ($p_reset) { // Reset request. sleep(3); include_once txpath . '/lib/txplib_admin.php'; $message = $p_userid ? send_reset_confirmation_request($p_userid) : ''; } elseif ($p_alter || $p_set) { // Password change/set confirmation. sleep(3); global $sitename; $pass = ps('p_password'); $type = $p_alter ? 'password_reset' : 'account_activation'; if (trim($pass) === '') { $message = array(gTxt('password_required'), E_ERROR); } else { $hash = gps('hash'); $selector = substr($hash, SALT_LENGTH); $tokenInfo = safe_row("reference_id, token, expires", 'txp_token', "selector = '" . doSlash($selector) . "' AND type='{$type}'"); if ($tokenInfo) { if (strtotime($tokenInfo['expires']) <= time()) { $message = array(gTxt('token_expired'), E_ERROR); } else { $uid = assert_int($tokenInfo['reference_id']); $row = safe_row("name, email, nonce, pass AS old_pass", 'txp_users', "user_id = {$uid}"); if ($row && $row['nonce'] && $hash === bin2hex(pack('H*', substr(hash(HASHING_ALGORITHM, $row['nonce'] . $selector . $row['old_pass']), 0, SALT_LENGTH))) . $selector) { if (change_user_password($row['name'], $pass)) { $body = gTxt('salutation', array('{name}' => $row['name'])) . n . n . ($p_alter ? gTxt('password_change_confirmation') : gTxt('password_set_confirmation') . n . n . gTxt('log_in_at') . ': ' . hu . 'textpattern/index.php'); $message = $p_alter ? gTxt('password_changed') : gTxt('password_set'); txpMail($row['email'], "[{$sitename}] " . $message, $body); // Invalidate all tokens in the wild for this user. safe_delete("txp_token", "reference_id = {$uid} AND type IN ('password_reset', 'account_activation')"); } } else { $message = array(gTxt('invalid_token'), E_ERROR); } } } else { $message = array(gTxt('invalid_token'), E_ERROR); } } } $txp_user = ''; return $message; }
function mem_self_password_form_submit() { global $prefs, $txp_user, $ign_user, $mem_form_type, $mem_form_values, $mem_form_thanks_form, $mem_self; if ($mem_form_type != 'mem_self_password') { return; } $verify_old = array_key_exists('old_password', $mem_form_values); $confirm = array_key_exists('password_confrim', $mem_form_values); $new_pass = $mem_form_values['password']; $old_pass = $mem_form_values['old_password']; $user = isset($ign_user) ? $ign_user : $txp_user; $where = "name = '" . doSlash($user) . "'"; $is_valid = $verify_old ? txp_validate($user, $old_pass) : true; if (!$is_valid) { return mem_form_error(mem_self_gTxt('password_invalid')); } if ($confirm and $new_pass != $mem_form_values['password_confirm']) { return mem_form_error(mem_self_gTxt('password_mismatch')); } $rs = safe_update(mem_get_user_table_name(), "pass = password(lower('{$new_pass}'))", $where); if (!$rs) { return mem_form_error(mem_self_gTxt('password_change_failed')); } // successful $mem_profile = safe_row('*', mem_get_user_table_name(), "name = '{$user}'"); if ($mem_profile) { $mem_profile['new_pass'] = $new_pass; $message = @fetch_form($mem_form_values['email_form']); if (!empty($message)) { $vals = $mem_form_values; $vals['sitename'] = $sitename; $vals['admin_name'] = $prefs['mem_self_admin_name']; $vals['admin_email'] = $vals['from']; $vals['password'] = $mem_profile['new_pass']; $vals['siteurl'] = hu; $vals['username'] = $vals['name']; foreach ($vals as $a => $b) { $message = str_replace('{' . $a . '}', $b, $message); $message = str_replace('<txp:mem_' . $a . ' />', $b, $message); } } else { $message = mem_self_gTxt('greeting', array('{name}' => $mem_form_values['RealName'])) . "\r\n" . mem_self_gTxt('your_password_is', array('{password}' => $new_pass)) . "\r\n" . mem_self_gTxt('log_in_at', array('{url}' => $mem_form_values['login_url'])); } $msg = parse($message); $to = $mem_profile['email']; $from = $mem_form_values['from']; $reply = $mem_form_values['reply']; $subject = $mem_form_values['subject']; if (mem_form_mail($from, $reply, $to, $subject, $msg)) { return mem_self_gTxt('password_changed'); } else { return mem_self_gTxt('password_changed_mail_failed'); } } else { // no email, fail silently } }