This commit is contained in:
Isaac Connor 2021-03-30 18:20:31 -04:00
parent 3d01008510
commit 6c4e423a8b
1 changed files with 33 additions and 34 deletions

View File

@ -63,7 +63,7 @@ function validateUser($username='', $password='') {
// local user, shouldn't affect the global user // local user, shouldn't affect the global user
$user = dbFetchOne($sql, NULL, array($username)); $user = dbFetchOne($sql, NULL, array($username));
if ( ! $user ) { if (!$user) {
return array(false, "Could not retrieve user $username details"); return array(false, "Could not retrieve user $username details");
} }
@ -97,7 +97,7 @@ function validateUser($username='', $password='') {
$password_correct = ($user['Password'] == $password); $password_correct = ($user['Password'] == $password);
} // switch password_type } // switch password_type
if ( $password_correct ) { if ($password_correct) {
return array($user, 'OK'); return array($user, 'OK');
} }
return array(false, "Login denied for user \"$username\""); return array(false, "Login denied for user \"$username\"");
@ -137,11 +137,11 @@ function validateToken($token, $allowed_token_type='access') {
$sql = 'SELECT * FROM Users WHERE Enabled=1 AND Username=?'; $sql = 'SELECT * FROM Users WHERE Enabled=1 AND Username=?';
$saved_user_details = dbFetchOne($sql, NULL, array($username)); $saved_user_details = dbFetchOne($sql, NULL, array($username));
if ( $saved_user_details ) { if ($saved_user_details) {
$issuedAt = $jwt_payload['iat']; $issuedAt = $jwt_payload['iat'];
$minIssuedAt = $saved_user_details['TokenMinExpiry']; $minIssuedAt = $saved_user_details['TokenMinExpiry'];
if ( $issuedAt < $minIssuedAt ) { if ($issuedAt < $minIssuedAt) {
ZM\Error("Token revoked for $username. Please generate a new token"); ZM\Error("Token revoked for $username. Please generate a new token");
$user = null;// unset only clears the local variable $user = null;// unset only clears the local variable
return array(false, 'Token revoked. Please re-generate'); return array(false, 'Token revoked. Please re-generate');
@ -155,9 +155,9 @@ function validateToken($token, $allowed_token_type='access') {
} // end function validateToken($token, $allowed_token_type='access') } // end function validateToken($token, $allowed_token_type='access')
function getAuthUser($auth) { function getAuthUser($auth) {
if ( ZM_OPT_USE_AUTH && (ZM_AUTH_RELAY == 'hashed') && !empty($auth) ) { if (ZM_OPT_USE_AUTH && (ZM_AUTH_RELAY == 'hashed') && !empty($auth)) {
$remoteAddr = ''; $remoteAddr = '';
if ( ZM_AUTH_HASH_IPS ) { if (ZM_AUTH_HASH_IPS) {
$remoteAddr = $_SERVER['REMOTE_ADDR']; $remoteAddr = $_SERVER['REMOTE_ADDR'];
if ( !$remoteAddr ) { if ( !$remoteAddr ) {
ZM\Error("Can't determine remote address for authentication, using empty string"); ZM\Error("Can't determine remote address for authentication, using empty string");
@ -165,41 +165,40 @@ function getAuthUser($auth) {
} }
} }
$sql = 'SELECT * FROM Users WHERE Enabled = 1';
$values = array(); $values = array();
if ( isset($_SESSION['username']) ) { if (isset($_SESSION['username'])) {
# Most of the time we will be logged in already and the session will have our username, so we can significantly speed up our hash testing by only looking at our user. # Most of the time we will be logged in already and the session will have our username, so we can significantly speed up our hash testing by only looking at our user.
# Only really important if you have a lot of users. # Only really important if you have a lot of users.
$sql = 'SELECT * FROM Users WHERE Enabled = 1 AND Username=?'; $sql .= ' AND Username=?';
array_push($values, $_SESSION['username']); array_push($values, $_SESSION['username']);
} else {
$sql = 'SELECT * FROM Users WHERE Enabled = 1';
} }
foreach ( dbFetchAll($sql, NULL, $values) as $user ) { foreach (dbFetchAll($sql, NULL, $values) as $user) {
$now = time(); $now = time();
for ( $i = 0; $i < ZM_AUTH_HASH_TTL; $i++, $now -= 3600 ) { // Try for last TTL hours for ($i = 0; $i < ZM_AUTH_HASH_TTL; $i++, $now -= 3600) { // Try for last TTL hours
$time = localtime($now); $time = localtime($now);
$authKey = ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$remoteAddr.$time[2].$time[3].$time[4].$time[5]; $authKey = ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$remoteAddr.$time[2].$time[3].$time[4].$time[5];
$authHash = md5($authKey); $authHash = md5($authKey);
if ( $auth == $authHash ) { if ($auth == $authHash) {
return $user; return $user;
} // end if $auth == $authHash } // end if $auth == $authHash
} // end foreach hour } // end foreach hour
} // end foreach user } // end foreach user
if ( isset($_SESSION['username']) ) { if (isset($_SESSION['username'])) {
# In a multi-server case, we might be logged in as another user and so the auth hash didn't work # In a multi-server case, we might be logged in as another user and so the auth hash didn't work
$sql = 'SELECT * FROM Users WHERE Enabled = 1 AND Username != ?'; $sql = 'SELECT * FROM Users WHERE Enabled = 1 AND Username != ?';
foreach ( dbFetchAll($sql, NULL, $values) as $user ) { foreach (dbFetchAll($sql, NULL, $values) as $user) {
$now = time(); $now = time();
for ( $i = 0; $i < ZM_AUTH_HASH_TTL; $i++, $now -= 3600 ) { // Try for last TTL hours for ($i = 0; $i < ZM_AUTH_HASH_TTL; $i++, $now -= 3600) { // Try for last TTL hours
$time = localtime($now); $time = localtime($now);
$authKey = ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$remoteAddr.$time[2].$time[3].$time[4].$time[5]; $authKey = ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$remoteAddr.$time[2].$time[3].$time[4].$time[5];
$authHash = md5($authKey); $authHash = md5($authKey);
if ( $auth == $authHash ) { if ($auth == $authHash) {
return $user; return $user;
} // end if $auth == $authHash } // end if $auth == $authHash
} // end foreach hour } // end foreach hour
@ -213,18 +212,18 @@ function getAuthUser($auth) {
function generateAuthHash($useRemoteAddr, $force=false) { function generateAuthHash($useRemoteAddr, $force=false) {
global $user; global $user;
if ( ZM_OPT_USE_AUTH and (ZM_AUTH_RELAY == 'hashed') and isset($user['Username']) and isset($user['Password']) ) { if (ZM_OPT_USE_AUTH and (ZM_AUTH_RELAY == 'hashed') and isset($user['Username']) and isset($user['Password'])) {
$time = time(); $time = time();
# We use 1800 so that we regenerate the hash at half the TTL # We use 1800 so that we regenerate the hash at half the TTL
$mintime = $time - ( ZM_AUTH_HASH_TTL * 1800 ); $mintime = $time - (ZM_AUTH_HASH_TTL * 1800);
# Appending the remoteAddr prevents us from using an auth hash generated for a different ip # Appending the remoteAddr prevents us from using an auth hash generated for a different ip
if ( $force or ( !isset($_SESSION['AuthHash'.$_SESSION['remoteAddr']]) ) or ( $_SESSION['AuthHashGeneratedAt'] < $mintime ) ) { if ($force or ( !isset($_SESSION['AuthHash'.$_SESSION['remoteAddr']]) ) or ( $_SESSION['AuthHashGeneratedAt'] < $mintime )) {
# Don't both regenerating Auth Hash if an hour hasn't gone by yet # Don't both regenerating Auth Hash if an hour hasn't gone by yet
$local_time = localtime(); $local_time = localtime();
$authKey = ''; $authKey = '';
if ( $useRemoteAddr ) { if ($useRemoteAddr) {
$authKey = ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$_SESSION['remoteAddr'].$local_time[2].$local_time[3].$local_time[4].$local_time[5]; $authKey = ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$_SESSION['remoteAddr'].$local_time[2].$local_time[3].$local_time[4].$local_time[5];
} else { } else {
$authKey = ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$local_time[2].$local_time[3].$local_time[4].$local_time[5]; $authKey = ZM_AUTH_HASH_SECRET.$user['Username'].$user['Password'].$local_time[2].$local_time[3].$local_time[4].$local_time[5];
@ -260,11 +259,11 @@ function canEdit($area, $mid=false) {
function userFromSession() { function userFromSession() {
$user = null; // Not global $user = null; // Not global
if ( isset($_SESSION['username']) ) { if (isset($_SESSION['username'])) {
if ( ZM_AUTH_HASH_LOGINS and (ZM_AUTH_RELAY == 'hashed') ) { if (ZM_AUTH_HASH_LOGINS and (ZM_AUTH_RELAY == 'hashed')) {
# Extra validation, if logged in, then the auth hash will be set in the session, so we can validate it. # Extra validation, if logged in, then the auth hash will be set in the session, so we can validate it.
# This prevent session modification to switch users # This prevent session modification to switch users
if ( isset($_SESSION['AuthHash'.$_SESSION['remoteAddr']]) ) if (isset($_SESSION['AuthHash'.$_SESSION['remoteAddr']]))
$user = getAuthUser($_SESSION['AuthHash'.$_SESSION['remoteAddr']]); $user = getAuthUser($_SESSION['AuthHash'.$_SESSION['remoteAddr']]);
else else
ZM\Debug('No auth hash in session, there should have been'); ZM\Debug('No auth hash in session, there should have been');
@ -278,13 +277,13 @@ function userFromSession() {
} }
function get_auth_relay() { function get_auth_relay() {
if ( ZM_OPT_USE_AUTH ) { if (ZM_OPT_USE_AUTH) {
if ( ZM_AUTH_RELAY == 'hashed' ) { if (ZM_AUTH_RELAY == 'hashed') {
return 'auth='.generateAuthHash(ZM_AUTH_HASH_IPS); return 'auth='.generateAuthHash(ZM_AUTH_HASH_IPS);
} else if ( ZM_AUTH_RELAY == 'plain' ) { } else if (ZM_AUTH_RELAY == 'plain') {
// password probably needs to be escaped // password probably needs to be escaped
return 'username='.$_SESSION['username'].'&password='.urlencode($_SESSION['password']); return 'username='.$_SESSION['username'].'&password='.urlencode($_SESSION['password']);
} else if ( ZM_AUTH_RELAY == 'none' ) { } else if (ZM_AUTH_RELAY == 'none') {
return 'username='.$_SESSION['username']; return 'username='.$_SESSION['username'];
} else { } else {
ZM\Error('Unknown value for ZM_AUTH_RELAY ' . ZM_AUTH_RELAY); ZM\Error('Unknown value for ZM_AUTH_RELAY ' . ZM_AUTH_RELAY);
@ -293,8 +292,8 @@ function get_auth_relay() {
return ''; return '';
} // end function get_auth_relay } // end function get_auth_relay
if ( ZM_OPT_USE_AUTH ) { if (ZM_OPT_USE_AUTH) {
if ( !empty($_REQUEST['token']) ) { if (!empty($_REQUEST['token'])) {
// we only need to get the username here // we only need to get the username here
// don't know the token type. That will // don't know the token type. That will
// be checked later // be checked later
@ -303,7 +302,7 @@ if ( ZM_OPT_USE_AUTH ) {
} else { } else {
// Non token based auth // Non token based auth
if ( ZM_AUTH_HASH_LOGINS && empty($user) && !empty($_REQUEST['auth']) ) { if (ZM_AUTH_HASH_LOGINS && empty($user) && !empty($_REQUEST['auth'])) {
$user = getAuthUser($_REQUEST['auth']); $user = getAuthUser($_REQUEST['auth']);
} else if ( } else if (
! ( ! (
@ -312,13 +311,13 @@ if ( ZM_OPT_USE_AUTH ) {
(defined('ZM_OPT_USE_GOOG_RECAPTCHA') && ZM_OPT_USE_GOOG_RECAPTCHA) (defined('ZM_OPT_USE_GOOG_RECAPTCHA') && ZM_OPT_USE_GOOG_RECAPTCHA)
) ) { ) ) {
$ret = validateUser($_REQUEST['username'], $_REQUEST['password']); $ret = validateUser($_REQUEST['username'], $_REQUEST['password']);
if ( !$ret[0] ) { if (!$ret[0]) {
ZM\Error($ret[1]); ZM\Error($ret[1]);
unset($user); // unset should be ok here because we aren't in a function unset($user); // unset should be ok here because we aren't in a function
return; return;
} }
$user = $ret[0]; $user = $ret[0];
} else if ( (ZM_AUTH_TYPE == 'remote') and !empty($_SERVER['REMOTE_USER']) ) { } else if ((ZM_AUTH_TYPE == 'remote') and !empty($_SERVER['REMOTE_USER'])) {
$sql = 'SELECT * FROM Users WHERE Enabled=1 AND Username=?'; $sql = 'SELECT * FROM Users WHERE Enabled=1 AND Username=?';
// local user, shouldn't affect the global user // local user, shouldn't affect the global user
$user = dbFetchOne($sql, NULL, array($_SERVER['REMOTE_USER'])); $user = dbFetchOne($sql, NULL, array($_SERVER['REMOTE_USER']));
@ -326,7 +325,7 @@ if ( ZM_OPT_USE_AUTH ) {
$user = userFromSession(); $user = userFromSession();
} }
if ( !empty($user) ) { if (!empty($user)) {
// generate it once here, while session is open. Value will be cached in session and return when called later on // generate it once here, while session is open. Value will be cached in session and return when called later on
generateAuthHash(ZM_AUTH_HASH_IPS); generateAuthHash(ZM_AUTH_HASH_IPS);
} }