MRBS 1.12.2 等保2.0二级整改完整提交
包含:登录失败锁定、90天密码有效期、30分钟会话超时、 强制改密、登录审计日志、屏幕水印、企业背景图、 备案信息固定底部、favicon、JS空集合保护、 会话过期体验优化(403 JSON)、display_errors 关闭、 固定 key 根治 Integrity check failed 等全部改动 注意:config.inc.php/.htaccess/.user.ini 含敏感信息, 通过 .gitignore 排除,勿推送到公开仓库。
This commit is contained in:
+491
@@ -0,0 +1,491 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace MRBS;
|
||||
|
||||
use MRBS\Auth\AuthFactory;
|
||||
use MRBS\Session\Session;
|
||||
use MRBS\Session\SessionFactory;
|
||||
|
||||
|
||||
// Convenience wrapper function to provide access to an Auth object
|
||||
function auth()
|
||||
{
|
||||
global $auth;
|
||||
|
||||
static $auth_obj = null;
|
||||
|
||||
if (is_null($auth_obj))
|
||||
{
|
||||
$auth_obj = AuthFactory::create($auth['type']);
|
||||
}
|
||||
|
||||
return $auth_obj;
|
||||
}
|
||||
|
||||
|
||||
// Convenience wrapper function to provide access to a Session object
|
||||
function session() : Session
|
||||
{
|
||||
global $auth;
|
||||
|
||||
static $session_obj = null;
|
||||
|
||||
if (is_null($session_obj))
|
||||
{
|
||||
$session_obj = SessionFactory::create($auth['session']);
|
||||
}
|
||||
|
||||
return $session_obj;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Checks if a page is open to users, using the config variables
|
||||
// $auth['only_admin_can_book'] and $auth['only_admin_can_book_before']
|
||||
function booking_level() : int
|
||||
{
|
||||
global $auth;
|
||||
|
||||
if ($auth['allow_anonymous_booking'])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($auth['only_admin_can_book'])
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
elseif ($auth['only_admin_can_book_before'])
|
||||
{
|
||||
$go_live = strtotime($auth['only_admin_can_book_before']);
|
||||
if ($go_live === false)
|
||||
{
|
||||
$message = "Could not calculate time from '" . $auth['only_admin_can_book_before'] . "'.";
|
||||
trigger_error($message);
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (time() >= $go_live) ? 1 : 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// Gets the minimum user level required to access a page
|
||||
function get_page_level($page)
|
||||
{
|
||||
global $auth, $max_level;
|
||||
|
||||
// If you're resetting your password you won't be logged in and $auth['deny_public_access']
|
||||
// should not apply. (change_password.php 同样放行:页面自身强制要求已登录,未登录会引导登录)
|
||||
if (in_array($page, array('reset_password.php', 'reset_password_handler.php', 'change_password.php')))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Otherwise ...
|
||||
switch ($page)
|
||||
{
|
||||
// These pages are open to the public by default as they only contain
|
||||
// read features.
|
||||
case 'help.php':
|
||||
case 'index.php':
|
||||
$result = 0;
|
||||
break;
|
||||
|
||||
// These pages reveal usernames, which could be of assistance to someone trying to
|
||||
// break into the system, so users are required to be logged in before viewing them.
|
||||
case 'search.php':
|
||||
$result = 1;
|
||||
break;
|
||||
|
||||
case 'view_entry.php':
|
||||
$result = ($auth['allow_anonymous_booking']) ? 0 : 1;
|
||||
break;
|
||||
|
||||
// These pages are set to have a minimum access level of 1 as ordinary users
|
||||
// should be able to access them because they will have read access and in some
|
||||
// cases write access for their own entries. Where necessary further checks are
|
||||
// made within the page to prevent ordinary users gaining access to admin features.
|
||||
case 'admin.php':
|
||||
case 'approve_entry_handler.php': // Ordinary users are allowed to remind admins
|
||||
case 'edit_message.php': // Booking admins can edit messages
|
||||
case 'edit_message_handler.php': // Booking admins can edit messages
|
||||
case 'edit_room.php': // Ordinary users can view room details
|
||||
case 'edit_users.php': // Ordinary users can edit their own details
|
||||
case 'pending.php': // Ordinary users can view their own entries
|
||||
case 'registration_handler.php': // Ordinary users can register for an event
|
||||
case 'usernames.php': // Ajax page for getting a list of users (booking admins can use this)
|
||||
$result = 1;
|
||||
break;
|
||||
|
||||
// These pages allow users to create and delete entries
|
||||
case 'check_slot.php': // Ajax page used by edit_entry.php
|
||||
case 'del_entry.php':
|
||||
case 'edit_entry.php':
|
||||
case 'edit_entry_handler.php':
|
||||
return booking_level();
|
||||
break;
|
||||
|
||||
// Everything else is for admins only
|
||||
default:
|
||||
$result = (isset($max_level)) ? $max_level : 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($auth['deny_public_access'])
|
||||
{
|
||||
$result = max($result, 1);
|
||||
}
|
||||
|
||||
// Can always access index.php when in kiosk mode
|
||||
if ($page == 'index.php' && is_kiosk_mode())
|
||||
{
|
||||
$result = 0;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/* getAuthorised($level)
|
||||
*
|
||||
* Check to see if the current user has a certain level of rights
|
||||
*
|
||||
* $level - The access level required
|
||||
* $returl - The URL to return to eventually
|
||||
*
|
||||
* Returns:
|
||||
* false - The user does not have the required access
|
||||
* true - The user has the required access
|
||||
*/
|
||||
function getAuthorised($level, $returl) : bool
|
||||
{
|
||||
// If the minimum level is zero (or not set) then they are
|
||||
// authorised, whoever they are
|
||||
if (empty($level))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise we need to check who they are
|
||||
$mrbs_user = session()->getCurrentUser();
|
||||
|
||||
if(!isset($mrbs_user))
|
||||
{
|
||||
// Ask them to authenticate, if the session scheme supports it
|
||||
if (method_exists(session(), 'authGet'))
|
||||
{
|
||||
session()->authGet(null, $returl);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return ($mrbs_user->level >= $level);
|
||||
}
|
||||
|
||||
|
||||
/* checkAuthorised()
|
||||
*
|
||||
* Checks to see that a user is authorised to access a page.
|
||||
* If they are not, then shows an "Access Denied" message and exits.
|
||||
*
|
||||
*/
|
||||
function checkAuthorised($page, $just_check=false)
|
||||
{
|
||||
global $view, $view_all, $year, $month, $day, $area, $room;
|
||||
global $returl;
|
||||
|
||||
// Get the minimum authorisation level for this page
|
||||
$required_level = get_page_level($page);
|
||||
|
||||
if ($just_check)
|
||||
{
|
||||
if ($required_level == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$mrbs_user = session()->getCurrentUser();
|
||||
return (isset($mrbs_user) && ($mrbs_user->level >= $required_level));
|
||||
}
|
||||
|
||||
// Check that the user has this level
|
||||
if (getAuthorised($required_level, $returl))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we don't know the right date then use today's
|
||||
if (!isset($day) or !isset($month) or !isset($year))
|
||||
{
|
||||
$day = date('d');
|
||||
$month = date('m');
|
||||
$year = date('Y');
|
||||
}
|
||||
|
||||
if (empty($area))
|
||||
{
|
||||
$area = get_default_area();
|
||||
}
|
||||
|
||||
showAccessDenied($view, $view_all, $year, $month, $day, $area, isset($room) ? $room : null);
|
||||
exit();
|
||||
}
|
||||
|
||||
|
||||
/* getWritable($creator, $room)
|
||||
*
|
||||
* Determines if the current user is able to modify an entry
|
||||
*
|
||||
* $creator - The creator of the entry
|
||||
* $rooms - The id(s) of the room(s) that the entries are in. Can
|
||||
* be a scalar or an array.
|
||||
* $all - Whether to check that the creator has write access
|
||||
* for all ($all=true) or just some ($all=false) of the
|
||||
* rooms.
|
||||
*
|
||||
* Returns:
|
||||
* false - The user does not have the required access
|
||||
* true - The user has the required access
|
||||
*/
|
||||
function getWritable($creator, $rooms=null, $all=true) : bool
|
||||
{
|
||||
if (is_array($rooms) && (count($rooms) > 0))
|
||||
{
|
||||
if ($all)
|
||||
{
|
||||
// We want the user to have write access for all the rooms,
|
||||
// so if for any one room they are not, then return false.
|
||||
foreach ($rooms as $room)
|
||||
{
|
||||
if (!getWritable($creator, $room))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We want the user to have write access for at least one room,
|
||||
// so if there are no rooms for which they do, then return false.
|
||||
foreach ($rooms as $room)
|
||||
{
|
||||
if (getWritable($creator, $room))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_null($rooms) && !$all)
|
||||
{
|
||||
// Not yet supported. Could support it but need to decide what $rooms=null means.
|
||||
// Does it mean all rooms in the system or just all rooms in the current area?
|
||||
throw new \Exception('$rooms===null and $all===false not yet supported.');
|
||||
}
|
||||
|
||||
// You can't make bookings in rooms which are invisible
|
||||
if (!is_visible($rooms))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Always allowed to modify your own stuff
|
||||
$mrbs_user = session()->getCurrentUser();
|
||||
if (isset($mrbs_user) && isset($creator) && (compare_usernames($creator, $mrbs_user->username) === 0))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise you have to be a (booking) admin for this room
|
||||
if (is_book_admin($rooms))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Unauthorised access
|
||||
return false;
|
||||
}
|
||||
|
||||
/* showAccessDenied()
|
||||
*
|
||||
* Displays an appropriate message when access has been denied
|
||||
*
|
||||
* Returns: Nothing
|
||||
*/
|
||||
function showAccessDenied($view=null, $view_all=null, $year=null, $month=null, $day=null, $area=null, $room=null)
|
||||
{
|
||||
global $server;
|
||||
|
||||
$context = array(
|
||||
'view' => $view,
|
||||
'view_all' => $view_all,
|
||||
'year' => $year,
|
||||
'month' => $month,
|
||||
'day' => $day,
|
||||
'area' => $area,
|
||||
'room' => isset($room) ? $room : null
|
||||
);
|
||||
|
||||
print_header($context);
|
||||
|
||||
// Wrap the contents in a <div> to help with styling. Not a very nice solution, but anyway.
|
||||
echo "<div>\n";
|
||||
echo "<h1>" . get_vocab("accessdenied") . "</h1>\n";
|
||||
echo "<p>" . get_vocab("norights") . "</p>\n";
|
||||
$referrer = session()->getReferrer();
|
||||
if (isset($referrer))
|
||||
{
|
||||
echo "<p>\n";
|
||||
echo "<a href=\"" . escape_html($referrer) . "\">\n" . get_vocab("returnprev") . "</a>\n";
|
||||
echo "</p>\n";
|
||||
}
|
||||
echo "</div>\n";
|
||||
|
||||
// Print footer and exit
|
||||
print_footer(true);
|
||||
}
|
||||
|
||||
|
||||
// Checks whether the current user has admin rights
|
||||
function is_admin() : bool
|
||||
{
|
||||
global $max_level;
|
||||
|
||||
$mrbs_user = session()->getCurrentUser();
|
||||
$required_level = (isset($max_level) ? $max_level : 2);
|
||||
|
||||
return (isset($mrbs_user) && ($mrbs_user->level >= $required_level));
|
||||
}
|
||||
|
||||
|
||||
// Checks whether the current user has booking administration rights
|
||||
// for $rooms - ie is allowed to modify and delete other people's bookings
|
||||
// and to approve bookings.
|
||||
//
|
||||
// $rooms can be either a single scalar value or an array of room ids. The default
|
||||
// value for $rooms is all rooms. (At the moment $room is ignored, but is passed here
|
||||
// so that later MRBS can be enhanced to provide fine-grained permissions.)
|
||||
//
|
||||
// $all specifies whether the user must be a booking for all $rooms, or just some of
|
||||
// them, ie at least one.
|
||||
//
|
||||
// Returns: TRUE if the user is allowed has booking admin rights for
|
||||
// the room(s); otherwise FALSE
|
||||
function is_book_admin($rooms=null, $all=true) : bool
|
||||
{
|
||||
global $min_booking_admin_level;
|
||||
|
||||
if (is_array($rooms) && (count($rooms) > 0))
|
||||
{
|
||||
if ($all)
|
||||
{
|
||||
// We want the user to be a booking admin for all the rooms,
|
||||
// so if for any one room they are not, then return false.
|
||||
foreach ($rooms as $room)
|
||||
{
|
||||
if (!is_book_admin($room))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We want the user to be a booking admin for at least one room,
|
||||
// so if there are no rooms for which they are, then return false.
|
||||
foreach ($rooms as $room)
|
||||
{
|
||||
if (is_book_admin($room))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_null($rooms) && !$all)
|
||||
{
|
||||
// Not yet supported. Could support it but need to decide what $rooms=null means.
|
||||
// Does it mean all rooms in the system or just all rooms in the current area?
|
||||
throw new \Exception('$rooms===null and $all===false not yet supported.');
|
||||
}
|
||||
|
||||
$mrbs_user = session()->getCurrentUser();
|
||||
|
||||
return (isset($mrbs_user) && ($mrbs_user->level >= $min_booking_admin_level));
|
||||
}
|
||||
|
||||
|
||||
// Checks whether the current user has user editing rights
|
||||
function is_user_admin() : bool
|
||||
{
|
||||
global $min_user_editing_level;
|
||||
|
||||
$mrbs_user = session()->getCurrentUser();
|
||||
|
||||
return (isset($mrbs_user) && ($mrbs_user->level >= $min_user_editing_level));
|
||||
}
|
||||
|
||||
|
||||
// Checks whether a room is visible to the current user
|
||||
// Doesn't do anything at the moment, but allows for customisation or future development
|
||||
function is_visible($room) : bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Checks whether a user is allowed to register other users for events
|
||||
function can_register_others($room_id=null) : bool
|
||||
{
|
||||
global $auth;
|
||||
|
||||
$mrbs_user = session()->getCurrentUser();
|
||||
|
||||
if (!isset($mrbs_user))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return $auth['users_can_register_others'] || is_book_admin($room_id);
|
||||
}
|
||||
|
||||
|
||||
// Checks whether the current user can see others' email addresses
|
||||
function can_see_email_addresses() : bool
|
||||
{
|
||||
global $auth, $is_private_field;
|
||||
|
||||
// Admins can see everything
|
||||
if (is_admin())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$mrbs_user = session()->getCurrentUser();
|
||||
|
||||
// Don't expose email addresses to the public
|
||||
if (!isset($mrbs_user))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// MRBS must be configured for logged-in users to see others' details
|
||||
if ($auth['only_admin_can_see_other_users'])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise the email field in the users table must not be private
|
||||
return (!auth()->canCreateUsers() || empty($is_private_field['users.email']));
|
||||
}
|
||||
Reference in New Issue
Block a user