Refactor ntbb-session with auth checking

Auth checking was done relatively sporadically in the past, but this
change adds $users->isSysop/isAdmin/isLeader for more centralized
auth checking.
This commit is contained in:
Guangcong Luo 2021-07-05 18:06:40 -04:00
parent ca91a728eb
commit 66238a9ee0
10 changed files with 65 additions and 52 deletions

View File

@ -4,7 +4,7 @@ require_once __DIR__ . '/../config/config.inc.php';
require_once __DIR__ . '/ntbb-database.lib.php';
// require_once dirname(__FILE__) . '/password_compat/lib/password.php';
$curuser = false;
$curuser = null;
class NTBBSession {
var $trustedproxies = array(
@ -82,9 +82,9 @@ class NTBBSession {
$curuser['loggedin'] = true;
// unset these values to avoid them being leaked accidentally
$curuser['outdatedpassword'] = !!$curuser['password'];
unset($curuser['password']);
unset($curuser['nonce']);
unset($curuser['passwordhash']);
$curuser['password'] = null;
$curuser['nonce'] = null;
$curuser['passwordhash'] = null;
$this->scookie = $scookie;
$this->session = $session;
@ -112,7 +112,7 @@ class NTBBSession {
return $ip;
}
function userid($username) {
function userid($username): string {
if (!$username) $username = '';
$username = strtr($username, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz");
return preg_replace('/[^A-Za-z0-9]+/','',$username);
@ -141,30 +141,26 @@ class NTBBSession {
/**
* New SID and password hashing functions.
*/
function mksid($osid) {
function mksid(string $osid) {
if (function_exists('psconfig_mksid')) {
return psconfig_mksid($osid);
}
return substr(base64_encode(random_bytes(18)), 0, 24);
}
function sidHash($sid) {
function sidHash(string $sid) {
global $psconfig;
return password_hash($sid, PASSWORD_DEFAULT, array('cost' => $psconfig['sid_cost']));
return password_hash($sid, PASSWORD_DEFAULT, ['cost' => $psconfig['sid_cost']]);
}
function passwordNeedsRehash($hash) {
function passwordNeedsRehash(string $hash) {
global $psconfig;
return password_needs_rehash($hash, PASSWORD_DEFAULT,
array('cost' => $psconfig['password_cost'])
);
return password_needs_rehash($hash, PASSWORD_DEFAULT, ['cost' => $psconfig['password_cost']]);
}
function passwordHash($pass) {
function passwordHash(string $pass) {
global $psconfig;
return password_hash($pass, PASSWORD_DEFAULT,
array('cost' => $psconfig['password_cost'])
);
return password_hash($pass, PASSWORD_DEFAULT, ['cost' => $psconfig['password_cost']]);
}
public function passwordVerify($name, $pass) {
public function passwordVerify(string $name, string $pass) {
global $psdb;
$userid = $this->userid($name);
@ -182,7 +178,7 @@ class NTBBSession {
return $this->passwordVerifyInner($userid, $pass, $user);
}
private function passwordVerifyInner($userid, $pass, $user) {
private function passwordVerifyInner(string $userid, string $pass, $user) {
global $psdb, $psconfig;
// throttle
@ -252,7 +248,7 @@ class NTBBSession {
return true;
}
function login($name, $pass, $timeout = false, $debug = false) {
function login(string $name, string $pass, $timeout = false, $debug = false) {
global $psdb, $curuser, $psconfig;
$ctime = time();
@ -354,7 +350,7 @@ class NTBBSession {
return $curuser;
}
function createPasswordResetToken($name, $timeout=false) {
function createPasswordResetToken(string $name, $timeout=false) {
global $psdb, $curuser;
$ctime = time();
@ -386,7 +382,7 @@ class NTBBSession {
return $token;
}
function validatePasswordResetToken($token) {
function validatePasswordResetToken(string $token) {
global $psdb, $psconfig;
if (strlen($token) !== ($psconfig['sid_length'] * 2)) return false;
$res = $psdb->query("SELECT * FROM `{$psdb->prefix}sessions` WHERE `sid` = ? LIMIT 1", [$token]);
@ -401,7 +397,7 @@ class NTBBSession {
return $session['userid'];
}
function getUser($userid=false) {
function getUser($userid = null) {
global $psdb, $curuser;
if ($userid === '0') return false;
@ -431,19 +427,19 @@ class NTBBSession {
return $user;
}
function getGroupName($user=false) {
function getGroupName($user = null) {
global $ntbb_cache;
$user = $this->getUser($user);
return @$ntbb_cache['groups'][$user['group']]['name'];
}
function getGroupSymbol($user=false) {
function getGroupSymbol($user = null) {
global $ntbb_cache;
$user = $this->getUser($user);
return @$ntbb_cache['groups'][$user['group']]['symbol'];
}
function getUserData($username) {
function getUserData(string $username) {
$userdata = $this->getUser($username);
if ($userdata) return $userdata;
@ -453,7 +449,7 @@ class NTBBSession {
return $userdata;
}
function getAssertion($userid, $serverhostname, $user = null, $challengekeyid = -1, $challenge = '', $challengeprefix = '') {
function getAssertion(string $userid, string $serverhostname, array $user = null, $challengekeyid = -1, $challenge = '', $challengeprefix = '') {
global $psdb, $curuser, $psconfig;
if (substr($userid, 0, 5) === 'guest') {
@ -583,7 +579,7 @@ class NTBBSession {
return $data.';'.bin2hex($sig);
}
function modifyUser($user, $changes) {
function modifyUser($user, array $changes) {
global $psdb, $curuser;
$userid = $user;
if (is_array($user)) $userid = $user['userid'];
@ -666,7 +662,7 @@ class NTBBSession {
return $user['registrationcount'];
}
function addUser($user, $password) {
function addUser(array $user, string $password) {
global $psdb, $curuser;
$ctime = time();
@ -696,13 +692,13 @@ class NTBBSession {
return $curuser;
}
function wordfilter($text) {
function wordfilter(string $text) {
$text = str_ireplace('lolicon', '*', $text);
$text = str_ireplace('roricon', '*', $text);
return $text;
}
function isUseridAllowed($userid) {
function isUseridAllowed(string $userid) {
if (strpos($userid, 'nigger') !== false) return false;
if (strpos($userid, 'nigga') !== false) return false;
if (strpos($userid, 'faggot') !== false) return false;
@ -711,6 +707,28 @@ class NTBBSession {
if (strpos($userid, 'lazyafrican') !== false) return false;
return true;
}
function isSysop(array $user = null) {
global $curuser, $psconfig;
if (!$user) $user = $curuser;
return in_array($user['userid'], $psconfig['sysops'], true);
}
function isAdmin(array $user = null) {
global $curuser;
if (!$user) $user = $curuser;
return ($user['group'] ?? 0) == 2;
}
/** unlike isAdmin, includes Smogon senior staff */
function isLeader(array $user = null) {
global $curuser;
if (!$user) $user = $curuser;
return ($user['group'] ?? 0) == 2 || ($user['group'] ?? 0) == 6;
}
}
$users = new NTBBSession();

View File

@ -19,7 +19,7 @@ $csrfOk = false;
if (isset($_REQUEST['manage'])) {
require_once '../lib/ntbb-session.lib.php';
if ($curuser['group'] != 2 && $curuser['group'] != 6) die("access denied");
if (!$users->isLeader()) die("access denied");
$csrfOk = !!$users->csrfCheck();
$manage = true;
header('Cache-Control: max-age=0, no-cache, no-store, must-revalidate');
@ -196,17 +196,15 @@ if (substr($replay['formatid'], -12) === 'randombattle' || substr($replay['forma
<?php
if ($panels->output === 'normal') {
?>
<div><script type="text/javascript"><!--
<div><script>
google_ad_client = "ca-pub-6535472412829264";
/* PS replay */
google_ad_slot = "6865298132";
google_ad_width = 728;
google_ad_height = 90;
//-->
</script>
<script type="text/javascript"
src="//pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div>
<script src="//pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</div>
<?php
}
?>

View File

@ -150,7 +150,7 @@ if (!$formatid) {
// we previously allowed all TLs to reset suspect ladders:
// substr($formatid, -11) === 'suspecttest' || substr($formatid, -7) === 'current'
// but that functionality got lost somewhere along the way
if (in_array($curuser['userid'], $psconfig['sysops'], true)) {
if ($users->isSysop()) {
$success = false;
if (@$_POST['act'] === 'resetladder' && $users->csrfCheck()) {
if ($_POST['confirm'] === "Permanently reset this ladder.") {

View File

@ -6,7 +6,7 @@ include_once '../../lib/ntbb-session.lib.php';
include_once __DIR__ . '/../../config/news.inc.php';
include_once 'include.php';
if (@$curuser['group'] != 2 && @$curuser['group'] != 6) die('access denied');
if (!$users->isLeader()) die('access denied');
function saveNews() {
global $newsCache, $latestNewsCache;

View File

@ -10,13 +10,11 @@ $pageTitle = "Servers";
$success = false;
$is_manager = (@$curuser['group'] == 2 || @$curuser['group'] == 6);
// Add server
//=================================================================================
if (@$_POST['act'] === 'addserver') {
if (!$is_manager) die('access denied');
if (!$users->isLeader()) die('access denied');
if (!$users->csrfCheck()) die('invalid data, please retry');
$name = trim(@$_POST['name']);
$owners = explode(',', @$_POST['owner']);
@ -97,7 +95,7 @@ uasort($inactiveservers, 'cmpByDate');
?>
<div class="main">
<?php
if ($is_manager) {
if ($users->isLeader()) {
?>
<h1>Add server</h1>
<p id="addserverbutton">
@ -182,7 +180,7 @@ foreach ($inactiveservers as $server) {
?>
</table>
<?php
if ($is_manager) {
if ($users->isLeader()) {
?>
<h1>Untracked servers</h1>
<p>

View File

@ -20,8 +20,6 @@ $pageTitle = "Servers";
$success = false;
$is_manager = (@$curuser['group'] == 2 || @$curuser['group'] == 6);
// Single server view
//=================================================================================
@ -48,8 +46,10 @@ if (!$entry) {
die("server not found");
}
$is_owner = $is_manager;
if (!@$entry['banned'] && strpos(','.@$entry['owner'].',', ','.$curuser['userid'].',') !== false) $is_owner = true;
$is_owner = $users->isLeader();
if (!@$entry['banned'] && strpos(','.@$entry['owner'].',', ','.$curuser['userid'].',') !== false) {
$is_owner = true;
}
if (@$_POST['act'] === 'editserver') {
if (!$is_owner) die('access denied');
@ -203,7 +203,7 @@ if (@$entry['token']) {
<button type="submit" name="act" value="editserver"><strong>Edit server</strong></button>
</div>
</form>
<?php if ($is_manager) { ?><form method="post">
<?php if ($users->isLeader()) { ?><form method="post">
<input type="hidden" name="act" value="deleteserver" /><?php $users->csrfData(); ?>
<p>
<button onclick="document.getElementById('deleteserver').style.display = 'block';return false"><small>Delete server</small></button> <button type="submit" id="deleteserver" style="display:none"><small><strong>I'm sure I want to delete this server</strong></small></button>

View File

@ -1,6 +1,5 @@
<?php
include_once __DIR__ . '/../../config/config.inc.php';
include_once __DIR__ . '/../../config/servers.inc.php';
include_once '../../lib/ntbb-session.lib.php';

View File

@ -13,7 +13,7 @@ include __DIR__ . '/lib/panels.lib.php';
$EMAIL_REGEX = '/(?:[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+\/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/i';
$lowerstaff = $curuser['group'] == 4 || $curuser['group'] == 5;
$upperstaff = $curuser['group'] == 2 || $curuser['group'] == 6;
$upperstaff = $users->isLeader();
if (!($lowerstaff || $upperstaff)) {
die("access denied");

View File

@ -372,7 +372,7 @@ if (!$user) {
?>
</div>
<?php
} else if (!$user['group'] && ($curuser['group'] == 2 || $curuser['group'] == 6)) {
} else if (!$user['group'] && $users->isLeader()) {
$csrfOk = false;
if ($users->csrfCheck()) {
$csrfOk = true;

View File

@ -16,7 +16,7 @@ $ip = @$_REQUEST['ip'];
$entry = @$_REQUEST['entry'];
$userlist = null;
if (!($curuser['group'] == 2 || $curuser['group'] == 6)) {
if (!$users->isLeader()) {
die("access denied");
}