<?php | |
function acl($_action, $_scope = null, $_data = null) { | |
global $pdo; | |
global $lang; | |
$_data_log = $_data; | |
switch ($_action) { | |
case 'edit': | |
switch ($_scope) { | |
case 'user': | |
if (!is_array($_data['username'])) { | |
$usernames = array(); | |
$usernames[] = $_data['username']; | |
} | |
else { | |
$usernames = $_data['username']; | |
} | |
foreach ($usernames as $username) { | |
// Cast to array for single selections | |
$acls = (array)$_data['user_acl']; | |
// Create associative array from index array | |
// All set items are given 1 as value | |
foreach ($acls as $acl_key => $acl_val) { | |
$acl_post[$acl_val] = 1; | |
} | |
// Users cannot change their own ACL | |
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username) | |
|| ($_SESSION['mailcow_cc_role'] != 'admin' && $_SESSION['mailcow_cc_role'] != 'domainadmin')) { | |
$_SESSION['return'][] = array( | |
'type' => 'danger', | |
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), | |
'msg' => 'access_denied' | |
); | |
continue; | |
} | |
// Read all available acl options by calling acl(get) | |
// Set all available acl options we cannot find in the post data to 0, else 1 | |
$is_now = acl('get', 'user', $username); | |
if (!empty($is_now)) { | |
foreach ($is_now as $acl_now_name => $acl_now_val) { | |
$set_acls[$acl_now_name] = (isset($acl_post[$acl_now_name])) ? 1 : 0; | |
} | |
} | |
else { | |
$_SESSION['return'][] = array( | |
'type' => 'danger', | |
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), | |
'msg' => 'Cannot determine current ACL' | |
); | |
continue; | |
} | |
foreach ($set_acls as $set_acl_key => $set_acl_val) { | |
$stmt = $pdo->prepare("UPDATE `user_acl` SET " . $set_acl_key . " = " . intval($set_acl_val) . " | |
WHERE `username` = :username"); | |
$stmt->execute(array( | |
':username' => $username, | |
)); | |
} | |
$_SESSION['return'][] = array( | |
'type' => 'success', | |
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), | |
'msg' => array('acl_saved', $username) | |
); | |
} | |
break; | |
case 'domainadmin': | |
if ($_SESSION['mailcow_cc_role'] != 'admin') { | |
$_SESSION['return'][] = array( | |
'type' => 'danger', | |
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), | |
'msg' => 'access_denied' | |
); | |
return false; | |
} | |
if (!is_array($_data['username'])) { | |
$usernames = array(); | |
$usernames[] = $_data['username']; | |
} | |
else { | |
$usernames = $_data['username']; | |
} | |
foreach ($usernames as $username) { | |
// Cast to array for single selections | |
$acls = (array)$_data['da_acl']; | |
// Create associative array from index array | |
// All set items are given 1 as value | |
foreach ($acls as $acl_key => $acl_val) { | |
$acl_post[$acl_val] = 1; | |
} | |
// Users cannot change their own ACL | |
if ($_SESSION['mailcow_cc_role'] != 'admin') { | |
$_SESSION['return'][] = array( | |
'type' => 'danger', | |
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), | |
'msg' => 'access_denied' | |
); | |
continue; | |
} | |
// Read all available acl options by calling acl(get) | |
// Set all available acl options we cannot find in the post data to 0, else 1 | |
$is_now = acl('get', 'domainadmin', $username); | |
if (!empty($is_now)) { | |
foreach ($is_now as $acl_now_name => $acl_now_val) { | |
$set_acls[$acl_now_name] = (isset($acl_post[$acl_now_name])) ? 1 : 0; | |
} | |
} | |
else { | |
$_SESSION['return'][] = array( | |
'type' => 'danger', | |
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), | |
'msg' => 'Cannot determine current ACL' | |
); | |
continue; | |
} | |
foreach ($set_acls as $set_acl_key => $set_acl_val) { | |
$stmt = $pdo->prepare("UPDATE `da_acl` SET " . $set_acl_key . " = " . intval($set_acl_val) . " | |
WHERE `username` = :username"); | |
$stmt->execute(array( | |
':username' => $username, | |
)); | |
} | |
$_SESSION['return'][] = array( | |
'type' => 'success', | |
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log), | |
'msg' => array('acl_saved', $username) | |
); | |
} | |
break; | |
} | |
break; | |
case 'get': | |
switch ($_scope) { | |
case 'user': | |
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { | |
return false; | |
} | |
$stmt = $pdo->prepare("SELECT * FROM `user_acl` WHERE `username` = :username"); | |
$stmt->execute(array(':username' => $_data)); | |
$data = $stmt->fetch(PDO::FETCH_ASSOC); | |
if ($_SESSION['mailcow_cc_role'] == 'domainadmin') { | |
// Domain admins cannot see, add or remove user ACLs they don't have access to by themselves | |
// Editing a user will use acl("get", "user") to determine granted ACLs and therefore block unallowed access escalation via form editing | |
$self_da_acl = acl('get', 'domainadmin', $_SESSION['mailcow_cc_username']); | |
foreach ($self_da_acl as $self_da_acl_key => $self_da_acl_val) { | |
if ($self_da_acl_val == 0) { | |
unset($data[$self_da_acl_key]); | |
} | |
} | |
} | |
if (!empty($data)) { | |
unset($data['username']); | |
return $data; | |
} | |
else { | |
return false; | |
} | |
break; | |
case 'domainadmin': | |
if ($_SESSION['mailcow_cc_role'] != 'admin' && $_SESSION['mailcow_cc_role'] != 'domainadmin') { | |
return false; | |
} | |
if ($_SESSION['mailcow_cc_role'] == 'domainadmin' && $_SESSION['mailcow_cc_username'] != $_data) { | |
return false; | |
} | |
$stmt = $pdo->prepare("SELECT * FROM `da_acl` WHERE `username` = :username"); | |
$stmt->execute(array(':username' => $_data)); | |
$data = $stmt->fetch(PDO::FETCH_ASSOC); | |
if (!empty($data)) { | |
unset($data['username']); | |
return $data; | |
} | |
else { | |
return false; | |
} | |
break; | |
} | |
break; | |
case 'to_session': | |
if (!isset($_SESSION['mailcow_cc_role'])) { | |
return false; | |
} | |
unset($_SESSION['acl']); | |
$username = strtolower(trim($_SESSION['mailcow_cc_username'])); | |
// Admins get access to all modules | |
if ($_SESSION['mailcow_cc_role'] == 'admin' || | |
(isset($_SESSION["dual-login"]["role"]) && $_SESSION["dual-login"]["role"] == 'admin')) { | |
$stmt = $pdo->query("SHOW COLUMNS FROM `user_acl` WHERE `Field` != 'username';"); | |
$acl_all = $stmt->fetchAll(PDO::FETCH_ASSOC); | |
while ($row = array_shift($acl_all)) { | |
$acl['acl'][$row['Field']] = 1; | |
} | |
$stmt = $pdo->query("SHOW COLUMNS FROM `da_acl` WHERE `Field` != 'username';"); | |
$acl_all = $stmt->fetchAll(PDO::FETCH_ASSOC); | |
while ($row = array_shift($acl_all)) { | |
$acl['acl'][$row['Field']] = 1; | |
} | |
} | |
elseif ($_SESSION['mailcow_cc_role'] == 'domainadmin' || | |
(isset($_SESSION["dual-login"]["role"]) && $_SESSION["dual-login"]["role"] == 'domainadmin')) { | |
// Read all exting user_acl modules and set to 1 | |
$stmt = $pdo->query("SHOW COLUMNS FROM `user_acl` WHERE `Field` != 'username';"); | |
$acl_all = $stmt->fetchAll(PDO::FETCH_ASSOC); | |
while ($row = array_shift($acl_all)) { | |
$acl['acl'][$row['Field']] = 1; | |
} | |
// Read da_acl rules for current user, OVERWRITE overlapping modules | |
// This prevents access to a users sync jobs, when a domain admins was not given access to sync jobs | |
$stmt = $pdo->prepare("SELECT * FROM `da_acl` WHERE `username` = :username"); | |
$stmt->execute(array(':username' => (isset($_SESSION["dual-login"]["username"])) ? $_SESSION["dual-login"]["username"] : $username)); | |
$acl_user = $stmt->fetch(PDO::FETCH_ASSOC); | |
foreach ($acl_user as $acl_user_key => $acl_user_val) { | |
$acl['acl'][$acl_user_key] = $acl_user_val; | |
} | |
unset($acl['acl']['username']); | |
} | |
elseif ($_SESSION['mailcow_cc_role'] == 'user') { | |
$stmt = $pdo->prepare("SELECT * FROM `user_acl` WHERE `username` = :username"); | |
$stmt->execute(array(':username' => $username)); | |
$acl['acl'] = $stmt->fetch(PDO::FETCH_ASSOC); | |
unset($acl['acl']['username']); | |
} | |
if (!empty($acl)) { | |
$_SESSION = array_merge($_SESSION, $acl); | |
} | |
break; | |
} | |
} |