Viewing file: security.php (24.37 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
class Security
{
public static function processPageSecurity( $table, $permission, $ajaxMode = false, $message = '' )
{
if( Security::checkPagePermissions( $table, $permission ) )
return true;
if( $ajaxMode )
{
Security::sendPermissionError( $message );
return false;
}
// The user is logged in but lacks necessary permissions
// redirect to Menu.
if( isLogged() && !isLoggedAsGuest() )
{
HeaderRedirect("menu");
return false;
}
// Not logged in
// redirect to Login
// Current URL is already saved in session
redirectToLogin();
return false;
}
public static function processAdminPageSecurity( $ajaxMode = false )
{
Security::processLogoutRequest();
if( !isLogged() || isLoggedAsGuest() )
{
Security::tryRelogin();
}
if( IsAdmin() )
return true;
if( $ajaxMode )
{
Security::sendPermissionError();
return false;
}
// The user is logged in but lacks necessary permissions
// redirect to Menu.
if( isLogged() && !isLoggedAsGuest() )
{
HeaderRedirect("menu");
return false;
}
// Not logged in
// redirect to Login
// Save current URL in session
Security::saveRedirectURL();
redirectToLogin();
return false;
}
public static function saveRedirectURL()
{
$url = $_SERVER["SCRIPT_NAME"];
$query = "";
// don't remember dashboard elements
if( postvalue("dashelement") )
return;
foreach( $_GET as $key=>$value )
{
if( $key == "a" && $value == "logout" )
continue;
if( $query != "" )
$query.="&";
if( is_array($value) )
{
$query .= rawurlencode($key."[]")."=";
$query .= implode( rawurlencode($key."[]")."=", $value );
}
else
{
$query .= rawurlencode($key);
if( strlen($value) )
$query .= "=" . rawurlencode($value);
}
}
if( $query != "" )
$url .= "?" . $query;
$_SESSION["MyURL"] = $url;
}
public static function checkPagePermissions( $table, $permission )
{
// log out if received ?a=logout request
Security::processLogoutRequest();
// save current URL
Security::saveRedirectURL();
$ret = Security::checkUserPermissions( $table, $permission );
// remember if current user has permissions on the page saved in $_SESSION[MyURL]
$_SESSION["MyUrlAccess"] = $ret;
return $ret;
}
protected static function createLoginPageObject()
{
include_once(getabspath('classes/loginpage.php'));
include_once(getabspath('include/xtempl.php'));
$loginXt = new Xtempl();
$loginParams = array("pageType" => PAGE_LOGIN);
$loginParams['id'] = -1;
$loginParams['xt'] = &$loginXt;
$loginParams["tName"]= GLOBAL_PAGES;
$loginParams['needSearchClauseObj'] = false;
$loginPageObject = new LoginPage($loginParams);
$loginPageObject->init();
return $loginPageObject;
}
/**
* Try to login automatically using saved login data
*/
static function tryRelogin()
{
// don't try if we have just logged out
if( postvalue("a") == "logout" )
return;
$loginPageObject = null;
// try to relogin with username & password from cookies first
$loginToken = postvalue("token");
if( !$loginToken ) {
$loginToken = $_COOKIE["token"];
}
if( $loginToken ) {
$tokenPayload = jwt_verify_decode( $loginToken );
if( $tokenPayload ) {
if( $tokenPayload["username"] ) {
$loginPageObject = Security::createLoginPageObject();
if( $loginPageObject->LogIn( $tokenPayload["username"], "", true ) )
{
return true;
}
}
}
// clear cookie if weren't able to login
setProjectCookie( "token", "", time() - 1, true );
}
// try security plugins
$securityPlugins = Security::GetPlugins();
foreach( $securityPlugins as $sp )
{
$token = $sp->savedToken();
if( $token ) {
if( !$loginPageObject )
$loginPageObject = Security::createLoginPageObject();
if( $loginPageObject->LoginWithSP( $sp, $token, false ) )
return true;
}
}
return false;
}
static function checkUserPermissions($table, $permission)
{
// user is logged in
if( !isLogged() || isLoggedAsGuest() )
{
Security::tryRelogin();
}
// admin area security
if( $table == ADMIN_USERS )
return IsAdmin();
return CheckTablePermissions($table, $permission);
}
/**
* Returns true if logged out
* @return Boolean
*/
static function processLogoutRequest()
{
// no need to logout
if( postvalue("a") != "logout" || !isLogged() || isLoggedAsGuest() )
return false;
// logout and redirect (refresh current page)
$loginPageObject = Security::createLoginPageObject();
$loginPageObject->Logout();
// login as guest
Security::doGuestLogin();
global $logoutPerformed;
$logoutPerformed = true;
return true;
}
/**
* @param String message (optional)
*/
public static function sendPermissionError( $message = '' )
{
echo printJSON(array("success" => false, "message" => "You don't have permissions to access this table".$message));
exit();
}
public static function redirectToList( $table )
{
$settings = new ProjectSettings( $table );
if( $settings->hasListPage() )
{
HeaderRedirect($settings->getShortTableName(), "list", "a=return");
exit();
}
// no List page
HeaderRedirect("menu");
exit();
}
public static function clearSecuritySession()
{
session_unset();
setProjectCookie("token", "", time() - 1, true );
// these lines are important
// DO NOT REMOVE THEM!
unset( $_COOKIE["username"] );
unset( $_COOKIE["password"] );
unset( $_COOKIE["token"] );
unset( $_SESSION["UserID"] );
unset( $_SESSION["UserName"] );
unset( $_SESSION["AccessLevel"] );
unset( $_SESSION["pluginLogin"] );
unset( $_SESSION["UserRights"] );
unset( $_SESSION["LastReadRights"] );
unset( $_SESSION['GroupID'] );
unset( $_SESSION["OwnerID"] );
unset( $_SESSION["securityOverrides"] );
$toClear = array();
foreach( $_SESSION as $k => $v )
{
if( substr($k, -8) == "_OwnerID" )
$toClear[] = $k;
if( substr($k, 0, 11) == "oauthToken_")
$toClear[] = $k;
}
foreach( $toClear as $k => $v )
{
unset( $_SESSION[ $k ] );
}
}
public static function doGuestLogin()
{
}
/**
* Security API calls
*/
/**
* Return current user's group when Static Permissions are used.
* When Dynamic permissions are used, returns any group name the user belongs to
* @return String
*/
public static function getUserGroup()
{
$userGroups = Security::getUserGroups();
foreach( $userGroups as $g => $v )
{
return $g;
}
return "";
}
/**
* Return array of the group IDs the user belongs to. Group Ids are the keys of the array:
* $groups[ <group1> ] = true;
* $groups[ <group2> ] = true;
* Admin group ID is -1
* When Static permissions are used, the array has only one element.
* Returns empty array when the user is Guest or not logged in.
* @return Array
*/
public static function getUserGroupIds()
{
global $globalSettings;
if( $globalSettings["nLoginMethod"] == SECURITY_NONE || $globalSettings["nLoginMethod"] == SECURITY_HARDCODED )
return array();
if( !$globalSettings["isDynamicPerm"] )
{
// static permissions
if( $_SESSION["GroupID"] )
return array( $_SESSION["GroupID"] => true );
return array();
}
// dynamic permissions
$groups = array();
foreach( $_SESSION["UserRights"][ $_SESSION["UserID"] ][ ".Groups" ] as $g )
$groups[$g] = true;
return $groups;
}
/**
* Return array of the group names the user belongs to. Group names are the keys of the array:
* $groups[ <group1> ] = true;
* $groups[ <group2> ] = true;
* When Static permissions option is used, the array has only one element.
* $groups[ <groupId> ] = true;
* Returns empty array when the user is Guest or not logged in or doesn't belong to any group.
* @return Array
*/
public static function getUserGroups()
{
global $globalSettings;
if( $globalSettings["nLoginMethod"] == SECURITY_NONE || $globalSettings["nLoginMethod"] == SECURITY_HARDCODED )
return array();
if( !$globalSettings["isDynamicPerm"] || $globalSettings["nLoginMethod"] == SECURITY_AD )
return Security::getUserGroupIds();
// database-based dynamic permissions
$groupIds = Security::getUserGroupIds();
$groupNames = array();
global $cman;
$grConnection = $cman->getForUserGroups();
$sql = "select ". $grConnection->addFieldWrappers( "" )
." from ". $grConnection->addTableWrappers( "uggroups" ) . " WHERE " . $grConnection->addFieldWrappers( "" )
." in ( " . implode( ",", array_keys( $groupIds ) ) . ")";
$qResult = $grConnection->query( $sql );
while( $data = $qResult->fetchNumeric() )
{
$groupNames[ $data[0] ] = true;
}
if( $groupIds[ -1 ] )
$groupNames["<Admin>"] = true;
return $groupNames;
}
/**
* Return current user's name, the same he entered when logging in.
* @return String
*/
public static function getUserName()
{
return $_SESSION["UserID"];
}
/**
* Return current user's display name, the one to be displayed on the pages.
* @return String
*/
public static function getDisplayName()
{
return $_SESSION["UserName"];
}
/**
* Change the current user's display name, the one to be displayed on the pages.
* @param String $str - new name, HTML formatting is allowed
*/
public static function setDisplayName( $str )
{
$_SESSION["UserName"] = $str;
}
/**
* Checks if the current user is Guest or not.
* @return Boolean
*/
public static function isGuest()
{
if($_SESSION["UserID"] == "Guest" && $_SESSION["AccessLevel"] == ACCESS_LEVEL_GUEST)
return true;
return false;
}
/**
* Checks if the current user is Admin or not.
* @return Boolean
*/
public static function isAdmin()
{
global $globalSettings;
if( $globalSettings["nLoginMethod"] == SECURITY_NONE || $globalSettings["nLoginMethod"] == SECURITY_HARDCODED )
return false;
// dynamic, DB or AD-based
if( $globalSettings["isDynamicPerm"] )
return $_SESSION["UserRights"][ $_SESSION["UserID"] ][ ".IsAdmin" ];
// static
if( $globalSettings["nLoginMethod"] == SECURITY_TABLE )
{
return ( ACCESS_LEVEL_ADMIN == $_SESSION["AccessLevel"] );
}
// no admins otherwise
return false;
}
/**
* Checks if the current user is logged in.
* @return Boolean
*/
public static function isLoggedIn()
{
return ( $_SESSION["UserID"] != "" && !Security::isGuest() );
}
/**
* Logs in under specified username
* @param String $username
* @param Boolean $fireEvents - call After Successful Login event or not
* @returns Boolean - true if login was successful
*/
public static function loginAs( $username, $fireEvents = true )
{
$loginPageObject = Security::createLoginPageObject();
return $loginPageObject->LogIn($username, "", true, $fireEvents );
}
/**
* @param String username
* @param String password
* @param Boolean fireEvents (optional) Run after unsuccessful event if login/password are incorrect.
* @return Boolean
*/
public static function checkUsernamePassword( $username, $password, $fireEvents = false )
{
$loginPageObject = Security::createLoginPageObject();
if( $loginPageObject->checkUsernamePassword( $username, $password ) )
return true;
if( $fireEvents )
{
$loginPageObject->doAfterUnsuccessfulLog( $username );
$loginPageObject->callAfterUnsuccessfulLoginEvent();
}
return false;
}
/**
* Check username/password and login if successful
* @param String username
* @param String password
* @param Boolean fireEvents (optional) Run after unsuccessful event if login/password are incorrect.
* @return Boolean
*/
public static function login( $username, $password, $fireEvents = true )
{
$loginPageObject = Security::createLoginPageObject();
return $loginPageObject->LogIn($username, $password, false, $fireEvents );
}
/**
* @param String username
* @param String password (optional)
* @return Array
*/
public static function getUserData( $username, $password = "" )
{
$loginPageObject = Security::createLoginPageObject();
return $loginPageObject->getUserData( $username, $password, "" == $password );
}
/**
* @return Array
*/
public static function currentUserData( )
{
return $_SESSION["UserData"];
}
/**
* Logs the current user out
*/
public static function logout()
{
$loginPageObject = Security::createLoginPageObject();
$loginPageObject->Logout();
}
/**
* Returns table permissions array the current user.
* Returns array where keys are specific permission letters:
* A - add,
* D - delete,
* E - edit,
* S - search/list,
* P - print/export,
* I - import,
* M - admin permission. When advanced permissions are in effect ( users can see/edit their own records only ), this permissions grants access to all records.
*
* Sample:
* $rights = Security::getPermissions( $table );
* if( $rights["A"] )
* echo "add permission available";
*
* @param String $table - table name
* @returns Array
*/
public static function getPermissions( $table )
{
$table = findTable( $table );
if( $table == "" )
return array();
return Security::permMask2Array( GetUserPermissions( $table ) );
}
/**
* Set table permissions for the current user.
* Permissions should be passed in the form of array where keys are specific permission letters:
* A - add,
* D - delete,
* E - edit,
* S - search/list,
* P - print/export,
* I - import,
* M - admin permission. When advanced permissions are in effect ( users can see/edit their own records only ), this permissions grants access to all records.
*
* Sample:
* $rights = Security::getPermissions( $table );
* $rights["A"] = true;
* $rights["D"] = false;
* Security::setPermissions( $table, $rights );
*
* Permissions need to be set only once per user session, i.e. in the 'After Successful Login' event.
*
* @param String $table - table name
* @param Array $rights
* @returns nothing
*/
public static function setPermissions( $table, $rights )
{
$table = findTable( $table );
if( $table == "" )
return;
$overrides =& Security::createSecurityOverrides( $table );
$overrides[ "mask" ] = Security::permArray2Mask( $rights );
}
private static function _setRestrictedPages( $table, $pageType, $pages, $pSet ) {
$currentPages = Security::getRestrictedPages( $table );
$newPages = array();
foreach( $currentPages as $p ) {
if( $pSet->getOriginalPageType( $p ) !== $pageType ) {
$newPages[ $p ] = true;
}
}
if( $pages ) {
foreach( $pages as $p ) {
$newPages[ $p ] = true;
}
}
$overrides =& Security::createSecurityOverrides( $table );
$overrides[ "pages" ] = $newPages;
$pSet->resetPages();
}
public static function setRestrictedPages( $table, $type, $pages )
{
if( $table !== GLOBAL_PAGES ) {
$table = findTable( $table );
if( $table == "" )
return;
}
if( !is_array( $pages ) ) {
$pages = array( $pages );
}
Security::_setRestrictedPages( $table, $pageType, $pages, new ProjectSettings( $table ) );
}
public static function setAllowedPages( $table, $type, $allowedPages )
{
if( $table !== GLOBAL_PAGES ) {
$table = findTable( $table );
if( $table == "" )
return;
}
if( !is_array( $allowedPages ) ) {
$allowedPages = array( $allowedPages );
}
$pSet = new ProjectSettings( $table );
$allPages = $pSet->getOriginalPagesByType( $type );
$pages = array();
foreach( $allPages as $p ) {
if( array_search( $p, $allowedPages ) === false )
$pages[] = $p;
}
Security::_setRestrictedPages( $table, $pageType, $pages, $pSet );
}
private static function & createSecurityOverrides( $table ) {
if( !isset( $_SESSION[ "securityOverrides" ] ) )
$_SESSION[ "securityOverrides" ] = array();
if( !isset( $_SESSION[ "securityOverrides" ][ $table ] ) )
$_SESSION[ "securityOverrides" ][ $table ] = array();
return $_SESSION[ "securityOverrides" ][ $table ];
}
private static function permMask2Array( $str )
{
$ret = array();
for( $i = 0; $i < strlen($str); ++$i )
{
$c = substr( $str, $i, 1 );
if( $c == "A" || $c == "D" || $c == "E" || $c == "S" || $c == "P" || $c == "I" || $c == "M" )
$ret[ $c ] = true;
}
return $ret;
}
private static function permArray2Mask( $rights )
{
$str = "";
if( !is_array( $rights ) )
{
if( strlen( $rights ) )
$rights = Security::permMask2Array( $rights );
else
return "";
}
foreach( $rights as $c => $v )
if( $v && ( $c == "A" || $c == "D" || $c == "E" || $c == "S" || $c == "P" || $c == "I" || $c == "M" ) )
$str .= $c;
return $str;
}
/**
* Returns current user's OwnerID - the value used to identify records ownership in the specific table.
*
* @param String $table - table name
* @returns String
*/
public static function getOwnerId( $table )
{
$table = findTable( $table );
if( $table == "" )
return;
return $_SESSION[ "_" . $table . "_OwnerID" ];
}
/**
* Change current user's OwnerID - the value used to identify records ownership in the specific table.
*
* @param String $table - table name
* @param String $ownerid
*/
public static function setOwnerId( $table, $ownerid )
{
$table = findTable( $table );
if( $table == "" )
return;
$_SESSION[ "_" . $table . "_OwnerID" ] = $ownerid;
}
public static function hasLogin() {
return GetGlobalData("createLoginPage");
}
public static function loginMethod() {
return GetGlobalData("nLoginMethod");
}
public static function dynamicPermissions() {
$method = Security::loginMethod();
if( $method != SECURITY_TABLE && $method != SECURITY_AD)
return false;
return GetGlobalData("isDynamicPerm");
}
/**
* Returns true if permissions are defined in the project.
* When false, no permissions system is present in the project. Everyone sees everything.
* @return Boolean
*/
public static function permissionsAvailable() {
$method = Security::loginMethod();
if( $method != SECURITY_TABLE && $method != SECURITY_AD )
return false;
return GetGlobalData("isDynamicPerm") || GetGlobalData("userGroupCount");
}
/**
* $permission - one of A,D,E,S,P,I literals
* $table that the permissions are requested on
* $ownerId - ownerId of the record the permissions is requested on
*/
public static function userCan( $permission, $table, $ownerId = null )
{
if( !Security::hasLogin() ) {
return true;
}
if($_SESSION["AccessLevel"] == ACCESS_LEVEL_ADMIN)
return true;
$strPerm = GetUserPermissions( $table );
// no permissions
if( strpos( $strPerm, $permission ) === false )
return false;
// record ownerId check not requested or user has admin permissions
if( $ownerId === null || strpos($strPerm, "M") !== false )
return true;
$pSet = new ProjectSettings($table);
$advSecType = $pSet->getAdvancedSecurityType();
if( $advSecType == ADVSECURITY_ALL || $advSecType == ADVSECURITY_NONE /*????*/ )
return true;
if( $advSecType == ADVSECURITY_EDIT_OWN && $permission != 'D' && $permission != 'E' ) {
return true;
}
$currentOwnerId = (string)$_SESSION["_".$table."_OwnerID"];
if( $pSet->isCaseInsensitiveUsername() ) {
$ownerId = strtoupper( $ownerId );
$currentOwnerId = strtoupper( $currentOwnerId );
}
return ( "".$ownerId ) === ( "".$currentOwnerId );
}
/**
* User has permissions on fields specified on the Register page and on the fields from pages he has access to
* pageName can be substituted by another page
*
* @param String table
* @param String field
* @param String pageType
* @param String pageName
* @param Boolean edit. Either we are asking to show field
*/
public static function userHasFieldPermissions( $table, $field, $pageType, $pageName, $edit ) {
global $cLoginTable;
$pageTable = $table;
if( $table === $cLoginTable && $pageType === "register") {
$pageTable = GLOBAL_PAGES;
}
$pSet = new ProjectSettings( $table, $pageType, $pageName, $pageTable );
$pageType = $pSet->getPageType();
$permission = Security::pageType2permission( $pageType );
if( $pageTable != GLOBAL_PAGES && !Security::userCan( $permission, $table ) ) {
return false;
}
// search panel fields
if( $edit && !pageTypeInputsData( $pageType ) ) {
if( $pSet->appearOnSearchPanel( $field ) ) {
return true;
}
if( $pageType == "list") {
return $pSet->hasInlineEdit() && $pSet->appearOnInlineEdit( $field )
|| $pSet->hasInlineAdd() && $pSet->appearOnInlineAdd( $field );
}
}
if( !$edit && !pageTypeShowsData( $pageType ) )
return false;
return $pSet->appearOnPage( $field );
}
public static function getRestrictedPages( $table )
{
if( is_array( $_SESSION["securityOverrides"] ) )
{
if( isset( $_SESSION["securityOverrides"][ $table ] ) ) {
if( isset( $_SESSION["securityOverrides"][ $table ][ "pages" ] ) ) {
return $_SESSION["securityOverrides"][ $table ][ "pages" ];
}
}
}
if( Security::dynamicPermissions() ) {
ReadUserPermissions();
$pages = @$_SESSION["UserRights"][$_SESSION["UserID"]][$table]["pages"];
if( !$pages ) {
$pages = array();
}
return $pages;
} else {
return Security::_staticRestrictedPages( $table );
}
return array();
}
public static function pageType2permission( $pageType ) {
if( $pageType == "add" )
return "A";
else if( $pageType == "edit" )
return "E";
else if( $pageType == "print" || $pageType == "export" || $pageType == "rprint" || $pageType == "masterprint" || $pageType == "masterrprint" )
return "P";
else if( $pageType == "import" )
return "I";
return "S";
}
public static function _staticRestrictedPages( $table ) {
$group = Security::getUserGroup();
// default permissions
return array();
}
public static function GetPlugins() {
$plugins = array();
require_once( getabspath('classes/security/securityplugin.php') );
if( GetGlobalData("isFB", false) )
{
require_once( getabspath( 'classes/security/fb.php' ) );
$plugins["fb"] = new SecurityPluginFB();
}
if( GetGlobalData("isGoogleSignIn", false) )
{
require_once( getabspath( 'classes/security/google.php' ) );
$plugins["go"] = new SecurityPluginGoogle();
}
return $plugins;
}
public static function getLoginTable() {
global $cLoginTable;
if( Security::loginMethod() === SECURITY_TABLE )
return $cLoginTable;
return false;
}
/**
* Test whether the user has permissions to see the page
*/
public static function userCanSeePage( $table, $page ) {
$pSet = new ProjectSettings( $table, "", $page );
if( $pSet->pageName() != $page )
return false;
if( $table == GLOBAL_PAGES )
return true;
$permission = Security::pageType2permission( $pSet->getPageType() );
if( !$permission ) {
// page doesn't require permissions
return true;
}
$strPerm = GetUserPermissions( $table );
return strpos( $strPerm, $permission ) !== false;
}
/**
* @param String - one of the permission letters: 'ADESPIM'
* @param ProjectSettings
* @return DsCondition or null if no condition needed
*/
public static function SelectCondition( $strRequestedPremission, $pSet )
{
// not a project table
if( !$pSet ) {
return null;
}
if( !Security::permissionsAvailable() ) {
return null;
}
if(@$_SESSION["AccessLevel"] == ACCESS_LEVEL_ADMIN) {
return null;
}
$strPerm = GetUserPermissions( $pSet->table() );
if( strpos( $strPerm, $strRequestedPremission ) === false ) {
return DataCondition::_False();
}
$ownerid = @$_SESSION["_" . $pSet->table() . "_OwnerID"];
$tableAdvSecurity = $pSet->getAdvancedSecurityType();
if( strpos($strPerm, "M") !== false ) {
return null;
}
if ( $tableAdvSecurity == ADVSECURITY_VIEW_OWN
|| $tableAdvSecurity == ADVSECURITY_EDIT_OWN
&& ( $strRequestedPremission == "E" || $strRequestedPremission == "D") ) {
return DataCondition::FieldEquals( $pSet->getTableOwnerID(), $ownerid );
}
return null;
}
}
?>
|