Check effective rights for the login-as feature to improve the delegation model
and allow controlling the administration privileges in LDAP (#1834). This deprecates the config options 'kolab_auth_group', 'kolab_auth_role_value' and 'kolab_auth_allowed_tasks'. Admin privileges (per Roundcube task) and the required effective rights are now defined in 'kolab_auth_admin_rights'.
This commit is contained in:
parent
232b458be4
commit
1e0b0cdf9d
3 changed files with 90 additions and 40 deletions
|
@ -29,6 +29,9 @@ $config['kolab_auth_name'] = array('name', 'cn');
|
||||||
$config['kolab_auth_email'] = array('email');
|
$config['kolab_auth_email'] = array('email');
|
||||||
$config['kolab_auth_organization'] = array('organization');
|
$config['kolab_auth_organization'] = array('organization');
|
||||||
|
|
||||||
|
// Role field (from fieldmap configuration)
|
||||||
|
$config['kolab_auth_role'] = 'role';
|
||||||
|
|
||||||
// Template for user names displayed in the UI.
|
// Template for user names displayed in the UI.
|
||||||
// You can use all attributes from the 'fieldmap' property of the 'kolab_auth_addressbook' configuration
|
// You can use all attributes from the 'fieldmap' property of the 'kolab_auth_addressbook' configuration
|
||||||
$config['kolab_auth_user_displayname'] = '{name} ({ou})';
|
$config['kolab_auth_user_displayname'] = '{name} ({ou})';
|
||||||
|
@ -40,20 +43,17 @@ $config['kolab_auth_admin_password'] = '';
|
||||||
// Enable audit logging for abuse of administrative privileges.
|
// Enable audit logging for abuse of administrative privileges.
|
||||||
$config['kolab_auth_auditlog'] = false;
|
$config['kolab_auth_auditlog'] = false;
|
||||||
|
|
||||||
// Role field (from fieldmap configuration)
|
// As set of rules to define the required rights on the target entry
|
||||||
$config['kolab_auth_role'] = 'role';
|
// which allow an admin user to login as another user (the target).
|
||||||
// The required value for the role attribute to contain should the user be allowed
|
// The effective rights value refers to either entry level attribute level rights:
|
||||||
// to login as another user.
|
// * entry:[read|add|delete]
|
||||||
$config['kolab_auth_role_value'] = '';
|
// * attrib:<attribute-name>:[read|write|delete]
|
||||||
|
$config['kolab_auth_admin_rights'] = array(
|
||||||
// Administrative group name to which user must be assigned to
|
// Roundcube task => required effective right
|
||||||
// which adds privilege to login as another user.
|
'settings' => 'entry:read',
|
||||||
$config['kolab_auth_group'] = '';
|
'mail' => 'entry:delete',
|
||||||
|
'addressbook' => 'entry:delete',
|
||||||
// List of tasks to which admin has access when logged in as another user.
|
);
|
||||||
// To limit usage to Settings only use: array('settings'). Default: array() - all tasks.
|
|
||||||
// When defined all non-authorized requests will be redirected to first task on the list.
|
|
||||||
$config['kolab_auth_allowed_tasks'] = array();
|
|
||||||
|
|
||||||
// Enable plugins on a role-by-role basis. In this example, the 'acl' plugin
|
// Enable plugins on a role-by-role basis. In this example, the 'acl' plugin
|
||||||
// is enabled for people with a 'cn=professional-user,dc=mykolab,dc=ch' role.
|
// is enabled for people with a 'cn=professional-user,dc=mykolab,dc=ch' role.
|
||||||
|
|
|
@ -91,12 +91,12 @@ class kolab_auth extends rcube_plugin
|
||||||
$rcmail = rcube::get_instance();
|
$rcmail = rcube::get_instance();
|
||||||
|
|
||||||
// Check access rights when logged in as another user
|
// Check access rights when logged in as another user
|
||||||
if (!empty($_SESSION['kolab_auth_admin']) && $rcmail->task != 'login' && $rcmail->task != 'logout') {
|
if (!empty($_SESSION['kolab_auth_admin']) && $args['task'] != 'login' && $args['task'] != 'logout') {
|
||||||
$tasks = $rcmail->config->get('kolab_auth_allowed_tasks');
|
|
||||||
// access to specified task is forbidden,
|
// access to specified task is forbidden,
|
||||||
// redirect to the first task on the list
|
// redirect to the first task on the list
|
||||||
if (!empty($tasks)) {
|
if (!empty($_SESSION['kolab_auth_allowed_tasks'])) {
|
||||||
if (!in_array($rcmail->task, (array) $tasks)) {
|
$tasks = (array)$_SESSION['kolab_auth_allowed_tasks'];
|
||||||
|
if (!in_array($args['task'], $tasks)) {
|
||||||
header('Location: ?_task=' . array_shift($tasks));
|
header('Location: ?_task=' . array_shift($tasks));
|
||||||
die;
|
die;
|
||||||
}
|
}
|
||||||
|
@ -451,24 +451,69 @@ class kolab_auth extends rcube_plugin
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the original user has/belongs to administrative role/group
|
|
||||||
$isadmin = false;
|
$isadmin = false;
|
||||||
$group = $rcmail->config->get('kolab_auth_group');
|
$admin_rights = $rcmail->config->get('kolab_auth_admin_rights', array());
|
||||||
$role_dn = $rcmail->config->get('kolab_auth_role_value');
|
|
||||||
|
|
||||||
// check role attribute
|
// @deprecated: fall-back to the old check if the original user has/belongs to administrative role/group
|
||||||
if (!empty($role_attr) && !empty($role_dn) && !empty($record[$role_attr])) {
|
if (empty($admin_rights)) {
|
||||||
$role_dn = $ldap->parse_vars($role_dn, $user, $host);
|
$group = $rcmail->config->get('kolab_auth_group');
|
||||||
if (in_array($role_dn, (array)$record[$role_attr])) {
|
$role_dn = $rcmail->config->get('kolab_auth_role_value');
|
||||||
$isadmin = true;
|
|
||||||
|
// check role attribute
|
||||||
|
if (!empty($role_attr) && !empty($role_dn) && !empty($record[$role_attr])) {
|
||||||
|
$role_dn = $ldap->parse_vars($role_dn, $user, $host);
|
||||||
|
if (in_array($role_dn, (array)$record[$role_attr])) {
|
||||||
|
$isadmin = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check group
|
||||||
|
if (!$isadmin && !empty($group)) {
|
||||||
|
$groups = $ldap->get_user_groups($record['dn'], $user, $host);
|
||||||
|
if (in_array($group, $groups)) {
|
||||||
|
$isadmin = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($isadmin) {
|
||||||
|
// user has admin privileges privilage, get "login as" user credentials
|
||||||
|
$target_entry = $ldap->get_user_record($loginas, $host);
|
||||||
|
$allowed_tasks = $rcmail->config->get('kolab_auth_allowed_tasks');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// get "login as" user credentials
|
||||||
|
$target_entry = $ldap->get_user_record($loginas, $host);
|
||||||
|
|
||||||
// check group
|
if (!empty($target_entry)) {
|
||||||
if (!$isadmin && !empty($group)) {
|
// get effective rights to determine login-as permissions
|
||||||
$groups = $ldap->get_user_groups($record['dn'], $user, $host);
|
$effective_rights = (array)$ldap->effective_rights($target_entry['dn']);
|
||||||
if (in_array($group, $groups)) {
|
|
||||||
$isadmin = true;
|
if (!empty($effective_rights)) {
|
||||||
|
$effective_rights['attrib'] = $effective_rights['attributeLevelRights'];
|
||||||
|
$effective_rights['entry'] = $effective_rights['entryLevelRights'];
|
||||||
|
|
||||||
|
// compare the rights with the permissions mapping
|
||||||
|
$allowed_tasks = array();
|
||||||
|
foreach ($admin_rights as $task => $perms) {
|
||||||
|
$perms_ = explode(':', $perms);
|
||||||
|
$type = array_shift($perms_);
|
||||||
|
$req = array_pop($perms_);
|
||||||
|
$attrib = array_pop($perms_);
|
||||||
|
|
||||||
|
if (array_key_exists($type, $effective_rights)) {
|
||||||
|
if ($type == 'entry' && in_array($req, $effective_rights[$type])) {
|
||||||
|
$allowed_tasks[] = $task;
|
||||||
|
}
|
||||||
|
else if ($type == 'attrib' && array_key_exists($attrib, $effective_rights[$type]) &&
|
||||||
|
in_array($req, $effective_rights[$type][$attrib])) {
|
||||||
|
$allowed_tasks[] = $task;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$isadmin = !empty($allowed_tasks);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,22 +525,22 @@ class kolab_auth extends rcube_plugin
|
||||||
$origname = $user;
|
$origname = $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
$record = null;
|
if (!$isadmin || empty($target_entry)) {
|
||||||
|
$this->add_texts('localization/');
|
||||||
|
|
||||||
// user has the privilage, get "login as" user credentials
|
|
||||||
if ($isadmin) {
|
|
||||||
$record = $ldap->get_user_record($loginas, $host);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($record)) {
|
|
||||||
$args['abort'] = true;
|
$args['abort'] = true;
|
||||||
|
$args['error'] = $this->gettext(array(
|
||||||
|
'name' => 'loginasnotallowed',
|
||||||
|
'vars' => array('user' => Q($loginas)),
|
||||||
|
));
|
||||||
|
|
||||||
$message = sprintf(
|
$message = sprintf(
|
||||||
'Login failure for user %s (as user %s) from %s in session %s (error %s)',
|
'Login failure for user %s (as user %s) from %s in session %s (error %s)',
|
||||||
$user,
|
$user,
|
||||||
$loginas,
|
$loginas,
|
||||||
rcube_utils::remote_ip(),
|
rcube_utils::remote_ip(),
|
||||||
session_id(),
|
session_id(),
|
||||||
"No user record found for '" . $loginas . "'"
|
"No privileges to login as '" . $loginas . "'"
|
||||||
);
|
);
|
||||||
|
|
||||||
rcube::write_log('userlogins', $message);
|
rcube::write_log('userlogins', $message);
|
||||||
|
@ -503,12 +548,16 @@ class kolab_auth extends rcube_plugin
|
||||||
return $args;
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// replace $record with target entry
|
||||||
|
$record = $target_entry;
|
||||||
|
|
||||||
$args['user'] = $this->username = $loginas;
|
$args['user'] = $this->username = $loginas;
|
||||||
|
|
||||||
// Mark session to use SASL proxy for IMAP authentication
|
// Mark session to use SASL proxy for IMAP authentication
|
||||||
$_SESSION['kolab_auth_admin'] = strtolower($origname);
|
$_SESSION['kolab_auth_admin'] = strtolower($origname);
|
||||||
$_SESSION['kolab_auth_login'] = $rcmail->encrypt($admin_login);
|
$_SESSION['kolab_auth_login'] = $rcmail->encrypt($admin_login);
|
||||||
$_SESSION['kolab_auth_password'] = $rcmail->encrypt($admin_pass);
|
$_SESSION['kolab_auth_password'] = $rcmail->encrypt($admin_pass);
|
||||||
|
$_SESSION['kolab_auth_allowed_tasks'] = $allowed_tasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store UID and DN of logged user in session for use by other plugins
|
// Store UID and DN of logged user in session for use by other plugins
|
||||||
|
@ -662,7 +711,7 @@ class kolab_auth extends rcube_plugin
|
||||||
public function render_page($args)
|
public function render_page($args)
|
||||||
{
|
{
|
||||||
$rcmail = rcube::get_instance();
|
$rcmail = rcube::get_instance();
|
||||||
$tasks = $rcmail->config->get('kolab_auth_allowed_tasks');
|
$tasks = (array)$_SESSION['kolab_auth_allowed_tasks'];
|
||||||
$tasks[] = 'logout';
|
$tasks[] = 'logout';
|
||||||
|
|
||||||
// disable buttons in taskbar
|
// disable buttons in taskbar
|
||||||
|
|
|
@ -9,5 +9,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$labels['loginas'] = 'Login As';
|
$labels['loginas'] = 'Login As';
|
||||||
|
$labels['loginasnotallowed'] = 'No privileges to login as $user';
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
Loading…
Add table
Reference in a new issue